From a87720b7e2ebe21d0ddb78078835eecc11f4020e Mon Sep 17 00:00:00 2001 From: cmpadden Date: Sun, 29 Sep 2024 19:33:20 +0000 Subject: [PATCH] deploy: 90a587bd8b7f43a866800d6e62dea9eca8d5e818 --- 200.html | 14 +- 404.html | 14 +- _nuxt/-GjkDpfn.js | 1 + _nuxt/36DYiIQe.js | 1 - _nuxt/3aFKPIgF.js | 1 - _nuxt/4KDx6Qdh.js | 1 + _nuxt/{DRhtvB_q.js => 4ZR8vDGy.js} | 2 +- _nuxt/B09kizko.js | 1 - _nuxt/B16Ch1Rg.js | 1 - _nuxt/B1tmNyhF.js | 1 - _nuxt/B2jTtLqC.js | 1 - _nuxt/B44J2786.js | 1 + _nuxt/B7NK_Nbm.js | 1 - _nuxt/{eM-U89SY.js => B8Io8PDA.js} | 2 +- _nuxt/BGlOumKY.js | 1 + _nuxt/BMjn8cbr.js | 1 - _nuxt/{Bdjj16Wj.js => BN984TM9.js} | 2 +- _nuxt/BNTwU45X.js | 1 - _nuxt/{Dtl8qhH9.js => BPDZZsV6.js} | 2 +- _nuxt/BPNqVqzl.js | 1 + _nuxt/{Bg6Wkwu9.js => BRI1TGcF.js} | 2 +- _nuxt/BSSPlG-l.js | 1 + _nuxt/BT8WlydD.js | 1 + _nuxt/BUQkeXPm.js | 1 - _nuxt/BbJBDj-J.js | 1 - _nuxt/BbWmv1K-.js | 1 - _nuxt/Bf0jujID.js | 1 + _nuxt/Bildd8lj.js | 1 + _nuxt/{BTZnUlcA.js => BnxxK6MW.js} | 2 +- _nuxt/BoZ9Gzu9.js | 1 - _nuxt/BqhY8_CC.js | 1 + _nuxt/BwID1M5A.js | 1 + _nuxt/{Oa1zqAZH.js => BwySm3O-.js} | 2 +- _nuxt/C-6Jpe-m.js | 1 + _nuxt/C67JdZ9D.js | 1 + _nuxt/{BT7WDeVb.js => C6WZwVE2.js} | 2 +- _nuxt/{B25qHsMz.js => CAu-wKXH.js} | 2 +- _nuxt/CHuhJ_Er.js | 1 + _nuxt/CJD6qL-K.js | 1 - _nuxt/CM0LhmwP.js | 1 + _nuxt/CMGdJvMz.js | 1 - _nuxt/CReNMuyo.js | 1 - _nuxt/{t47rUjQB.js => CS4CKjMH.js} | 2 +- _nuxt/CXWT5P23.js | 1 + _nuxt/CYevVL6b.js | 1 + _nuxt/CZZfhpmp.js | 1658 ----------------- _nuxt/{CmpoAw97.js => Ce34VGij.js} | 4 +- _nuxt/CfFW-P5d.js | 1 + _nuxt/{BdajRVA-.js => CiJ7X6_i.js} | 2 +- _nuxt/{B-Suu3Ve.js => ClOZFDRl.js} | 2 +- _nuxt/Ct3Jmt0b.js | 1 - _nuxt/CuOPeUWs.js | 1 - _nuxt/CwlYhM_w.js | 1 + _nuxt/CxWdTzCB.js | 1 + _nuxt/D-xzt0Hk.js | 1 + _nuxt/D24cNfD5.js | 1 + _nuxt/D2yfouAe.js | 1 - _nuxt/D6go2xuX.js | 1 - _nuxt/DCZXcdSM.js | 1 + _nuxt/{BvT8JnCb.js => DJOb4bXW.js} | 2 +- _nuxt/DKixc0ER.js | 1 - _nuxt/DMa1cH9I.js | 1 - _nuxt/DOZLo8mA.js | 1 + _nuxt/DP6TDZ8u.js | 1 + _nuxt/DS2wgvBY.js | 1 - _nuxt/DV8CRu_y.js | 1 - _nuxt/DYh1WRot.js | 1 - _nuxt/Dab_E90i.js | 1 - _nuxt/{LT2DbrHy.js => DbroGl9h.js} | 2 +- _nuxt/{BacZaOvF.js => DcLi_FTb.js} | 2 +- _nuxt/Ddr6mL0e.js | 1 - _nuxt/{DbS0a68n.js => Des7KGkR.js} | 2 +- _nuxt/{CeHLcfh0.js => DjOkkdqj.js} | 4 +- _nuxt/{DwoF_sus.js => DltOabO9.js} | 2 +- _nuxt/Dnd51l0P.js | 1 - _nuxt/DrUr0h-s.js | 1 - _nuxt/DsILVI33.js | 1 + _nuxt/{DSVbkqRh.js => DsRHAFuR.js} | 2 +- _nuxt/{BExJZFgy.js => Dw08bDjX.js} | 2 +- _nuxt/{BsueCq5A.js => Dyf09I7x.js} | 2 +- _nuxt/Ie0IFvhY.js | 1 - _nuxt/Iio6RtF1.js | 1 + _nuxt/IzO1sTXP.js | 1 + _nuxt/K1dcBiIN.js | 1650 ++++++++++++++++ _nuxt/Ml_4v_Rc.js | 1 - _nuxt/{BDlA7Zky.js => N3o-VwNZ.js} | 2 +- _nuxt/NnUIAPGH.js | 1 + _nuxt/OorYyVAq.js | 1 + _nuxt/PIAawFjR.js | 1 - _nuxt/{DK7GvCoQ.js => SY0NXAMn.js} | 2 +- _nuxt/{Dj_Dm3AU.js => TE8sWSFL.js} | 2 +- _nuxt/{CZYXMW8W.js => WSSBFWCz.js} | 2 +- _nuxt/Xli_fklN.js | 1 - _nuxt/Zyr_YK_I.js | 1 - _nuxt/_5NWYBcI.js | 1 - _nuxt/builds/latest.json | 2 +- .../8ac6cfc2-8695-46be-9b06-7ad33f3a3d43.json | 1 - .../d6ca5b55-ea93-45cf-9a93-ac870132a3e2.json | 1 + _nuxt/g5yxyt4Q.js | 1 + _nuxt/gYgHqO9f.js | 1 - _nuxt/kCftLbeK.js | 1 - _nuxt/mDMTOJLw.js | 1 + _nuxt/nVRvli7B.js | 1 - _nuxt/{wpwljwju.js => pMxOCLTg.js} | 2 +- _nuxt/pTPauEmS.js | 1 + _nuxt/uYek0qF_.js | 1 + _nuxt/v3tOoUxe.js | 1 + _nuxt/{PCdpkuPO.js => v_KFgWUo.js} | 2 +- _nuxt/wDya3lie.js | 1 + _nuxt/y2Up_N_N.js | 1 + _payload.json | 2 +- api/_content/cache.1726174725311.json | 1 - api/_content/cache.1727638383380.json | 1 + ...311.json => 0ikQYfLQVZ.1727638383380.json} | 2 +- ...311.json => 0vuDGaHulu.1727638383380.json} | 2 +- ...311.json => 1BkkvizQw8.1727638383380.json} | 2 +- ...311.json => AwYZnKuAHr.1727638383380.json} | 2 +- ...311.json => C0SimRluqy.1727638383380.json} | 2 +- ...311.json => DIau8q3IMV.1727638383380.json} | 0 ...311.json => PYi9meWOqm.1727638383380.json} | 2 +- ...311.json => QB64GpMlA8.1727638383380.json} | 2 +- ...311.json => SFFy74pu72.1727638383380.json} | 2 +- ...311.json => TxpJ5sv0HY.1727638383380.json} | 2 +- ...311.json => bXj5vj6Ts0.1727638383380.json} | 0 ...311.json => cOxeB6k0CX.1727638383380.json} | 2 +- ...311.json => lIKyXFs9L8.1727638383380.json} | 2 +- ...311.json => ph6vNEpVOi.1727638383380.json} | 2 +- ...311.json => wVY7dvWXwt.1727638383380.json} | 2 +- ...311.json => x8mzqct7Ta.1727638383380.json} | 2 +- articles/_payload.json | 2 +- articles/apu2-firmware-upgrade/_payload.json | 2 +- articles/apu2-firmware-upgrade/index.html | 53 +- articles/docker-selinux-volumes/_payload.json | 2 +- articles/docker-selinux-volumes/index.html | 55 +- articles/doctl/_payload.json | 2 +- articles/doctl/index.html | 47 +- .../fennel-initial-exploration/_payload.json | 2 +- .../fennel-initial-exploration/index.html | 67 +- articles/index.html | 41 +- .../_payload.json | 2 +- .../index.html | 45 +- articles/nuxt-content-rss-feed/_payload.json | 2 +- articles/nuxt-content-rss-feed/index.html | 47 +- articles/nuxt-v3-migration/_payload.json | 2 +- articles/nuxt-v3-migration/index.html | 43 +- .../persistent-archlinux-usb/_payload.json | 2 +- articles/persistent-archlinux-usb/index.html | 55 +- .../_payload.json | 2 +- .../index.html | 47 +- .../_payload.json | 2 +- .../index.html | 47 +- .../_payload.json | 2 +- .../index.html | 47 +- articles/ssh-ed25519-sk-yubikey/_payload.json | 2 +- articles/ssh-ed25519-sk-yubikey/index.html | 49 +- .../_payload.json | 2 +- .../index.html | 53 +- .../vim-fugitive-gpg-pinentry/_payload.json | 2 +- articles/vim-fugitive-gpg-pinentry/index.html | 49 +- atom/index.html | 2 +- card/_payload.json | 2 +- card/index.html | 18 +- examples/nested_transitions/_payload.json | 2 +- examples/nested_transitions/index.html | 18 +- index.html | 24 +- playground/_payload.json | 2 +- playground/audio/_payload.json | 2 +- playground/audio/index.html | 18 +- playground/chords/_payload.json | 2 +- playground/chords/index.html | 18 +- playground/conway/_payload.json | 2 +- playground/conway/index.html | 18 +- playground/french/_payload.json | 2 +- playground/french/index.html | 20 +- playground/index.html | 20 +- playground/matrix/_payload.json | 2 +- playground/matrix/index.html | 18 +- playground/metronome/_payload.json | 2 +- playground/metronome/index.html | 18 +- playground/midi/_payload.json | 2 +- playground/midi/index.html | 18 +- playground/palettes/mountains/_payload.json | 2 +- playground/palettes/mountains/index.html | 18 +- playground/palettes/variance/_payload.json | 2 +- playground/palettes/variance/index.html | 18 +- playground/plotter/_payload.json | 2 +- playground/plotter/index.html | 18 +- playground/tiling/_payload.json | 2 +- playground/tiling/index.html | 18 +- playground/waves/_payload.json | 2 +- playground/waves/index.html | 18 +- talks/_payload.json | 2 +- talks/index.html | 18 +- 193 files changed, 2304 insertions(+), 2328 deletions(-) create mode 100644 _nuxt/-GjkDpfn.js delete mode 100644 _nuxt/36DYiIQe.js delete mode 100644 _nuxt/3aFKPIgF.js create mode 100644 _nuxt/4KDx6Qdh.js rename _nuxt/{DRhtvB_q.js => 4ZR8vDGy.js} (63%) delete mode 100644 _nuxt/B09kizko.js delete mode 100644 _nuxt/B16Ch1Rg.js delete mode 100644 _nuxt/B1tmNyhF.js delete mode 100644 _nuxt/B2jTtLqC.js create mode 100644 _nuxt/B44J2786.js delete mode 100644 _nuxt/B7NK_Nbm.js rename _nuxt/{eM-U89SY.js => B8Io8PDA.js} (65%) create mode 100644 _nuxt/BGlOumKY.js delete mode 100644 _nuxt/BMjn8cbr.js rename _nuxt/{Bdjj16Wj.js => BN984TM9.js} (65%) delete mode 100644 _nuxt/BNTwU45X.js rename _nuxt/{Dtl8qhH9.js => BPDZZsV6.js} (64%) create mode 100644 _nuxt/BPNqVqzl.js rename _nuxt/{Bg6Wkwu9.js => BRI1TGcF.js} (58%) create mode 100644 _nuxt/BSSPlG-l.js create mode 100644 _nuxt/BT8WlydD.js delete mode 100644 _nuxt/BUQkeXPm.js delete mode 100644 _nuxt/BbJBDj-J.js delete mode 100644 _nuxt/BbWmv1K-.js create mode 100644 _nuxt/Bf0jujID.js create mode 100644 _nuxt/Bildd8lj.js rename _nuxt/{BTZnUlcA.js => BnxxK6MW.js} (65%) delete mode 100644 _nuxt/BoZ9Gzu9.js create mode 100644 _nuxt/BqhY8_CC.js create mode 100644 _nuxt/BwID1M5A.js rename _nuxt/{Oa1zqAZH.js => BwySm3O-.js} (64%) create mode 100644 _nuxt/C-6Jpe-m.js create mode 100644 _nuxt/C67JdZ9D.js rename _nuxt/{BT7WDeVb.js => C6WZwVE2.js} (97%) rename _nuxt/{B25qHsMz.js => CAu-wKXH.js} (53%) create mode 100644 _nuxt/CHuhJ_Er.js delete mode 100644 _nuxt/CJD6qL-K.js create mode 100644 _nuxt/CM0LhmwP.js delete mode 100644 _nuxt/CMGdJvMz.js delete mode 100644 _nuxt/CReNMuyo.js rename _nuxt/{t47rUjQB.js => CS4CKjMH.js} (78%) create mode 100644 _nuxt/CXWT5P23.js create mode 100644 _nuxt/CYevVL6b.js delete mode 100644 _nuxt/CZZfhpmp.js rename _nuxt/{CmpoAw97.js => Ce34VGij.js} (76%) create mode 100644 _nuxt/CfFW-P5d.js rename _nuxt/{BdajRVA-.js => CiJ7X6_i.js} (71%) rename _nuxt/{B-Suu3Ve.js => ClOZFDRl.js} (64%) delete mode 100644 _nuxt/Ct3Jmt0b.js delete mode 100644 _nuxt/CuOPeUWs.js create mode 100644 _nuxt/CwlYhM_w.js create mode 100644 _nuxt/CxWdTzCB.js create mode 100644 _nuxt/D-xzt0Hk.js create mode 100644 _nuxt/D24cNfD5.js delete mode 100644 _nuxt/D2yfouAe.js delete mode 100644 _nuxt/D6go2xuX.js create mode 100644 _nuxt/DCZXcdSM.js rename _nuxt/{BvT8JnCb.js => DJOb4bXW.js} (65%) delete mode 100644 _nuxt/DKixc0ER.js delete mode 100644 _nuxt/DMa1cH9I.js create mode 100644 _nuxt/DOZLo8mA.js create mode 100644 _nuxt/DP6TDZ8u.js delete mode 100644 _nuxt/DS2wgvBY.js delete mode 100644 _nuxt/DV8CRu_y.js delete mode 100644 _nuxt/DYh1WRot.js delete mode 100644 _nuxt/Dab_E90i.js rename _nuxt/{LT2DbrHy.js => DbroGl9h.js} (56%) rename _nuxt/{BacZaOvF.js => DcLi_FTb.js} (63%) delete mode 100644 _nuxt/Ddr6mL0e.js rename _nuxt/{DbS0a68n.js => Des7KGkR.js} (77%) rename _nuxt/{CeHLcfh0.js => DjOkkdqj.js} (72%) rename _nuxt/{DwoF_sus.js => DltOabO9.js} (82%) delete mode 100644 _nuxt/Dnd51l0P.js delete mode 100644 _nuxt/DrUr0h-s.js create mode 100644 _nuxt/DsILVI33.js rename _nuxt/{DSVbkqRh.js => DsRHAFuR.js} (92%) rename _nuxt/{BExJZFgy.js => Dw08bDjX.js} (75%) rename _nuxt/{BsueCq5A.js => Dyf09I7x.js} (65%) delete mode 100644 _nuxt/Ie0IFvhY.js create mode 100644 _nuxt/Iio6RtF1.js create mode 100644 _nuxt/IzO1sTXP.js create mode 100644 _nuxt/K1dcBiIN.js delete mode 100644 _nuxt/Ml_4v_Rc.js rename _nuxt/{BDlA7Zky.js => N3o-VwNZ.js} (64%) create mode 100644 _nuxt/NnUIAPGH.js create mode 100644 _nuxt/OorYyVAq.js delete mode 100644 _nuxt/PIAawFjR.js rename _nuxt/{DK7GvCoQ.js => SY0NXAMn.js} (64%) rename _nuxt/{Dj_Dm3AU.js => TE8sWSFL.js} (64%) rename _nuxt/{CZYXMW8W.js => WSSBFWCz.js} (79%) delete mode 100644 _nuxt/Xli_fklN.js delete mode 100644 _nuxt/Zyr_YK_I.js delete mode 100644 _nuxt/_5NWYBcI.js delete mode 100644 _nuxt/builds/meta/8ac6cfc2-8695-46be-9b06-7ad33f3a3d43.json create mode 100644 _nuxt/builds/meta/d6ca5b55-ea93-45cf-9a93-ac870132a3e2.json create mode 100644 _nuxt/g5yxyt4Q.js delete mode 100644 _nuxt/gYgHqO9f.js delete mode 100644 _nuxt/kCftLbeK.js create mode 100644 _nuxt/mDMTOJLw.js delete mode 100644 _nuxt/nVRvli7B.js rename _nuxt/{wpwljwju.js => pMxOCLTg.js} (65%) create mode 100644 _nuxt/pTPauEmS.js create mode 100644 _nuxt/uYek0qF_.js create mode 100644 _nuxt/v3tOoUxe.js rename _nuxt/{PCdpkuPO.js => v_KFgWUo.js} (64%) create mode 100644 _nuxt/wDya3lie.js create mode 100644 _nuxt/y2Up_N_N.js delete mode 100644 api/_content/cache.1726174725311.json create mode 100644 api/_content/cache.1727638383380.json rename api/_content/query/{QmL7G3Pk7i.1726174725311.json => 0ikQYfLQVZ.1727638383380.json} (99%) rename api/_content/query/{XgcK3x9EBy.1726174725311.json => 0vuDGaHulu.1727638383380.json} (99%) rename api/_content/query/{6WfgQ5T9tH.1726174725311.json => 1BkkvizQw8.1727638383380.json} (99%) rename api/_content/query/{ZzD9WRl1Uk.1726174725311.json => AwYZnKuAHr.1727638383380.json} (81%) rename api/_content/query/{Nr5UObwduV.1726174725311.json => C0SimRluqy.1727638383380.json} (98%) rename api/_content/query/{DIau8q3IMV.1726174725311.json => DIau8q3IMV.1727638383380.json} (100%) rename api/_content/query/{tGrf8kFZOz.1726174725311.json => PYi9meWOqm.1727638383380.json} (98%) rename api/_content/query/{pfbAdBSC9a.1726174725311.json => QB64GpMlA8.1727638383380.json} (99%) rename api/_content/query/{TDaCLaQ73L.1726174725311.json => SFFy74pu72.1727638383380.json} (98%) rename api/_content/query/{7TfxHWYxZH.1726174725311.json => TxpJ5sv0HY.1727638383380.json} (53%) rename api/_content/query/{bXj5vj6Ts0.1726174725311.json => bXj5vj6Ts0.1727638383380.json} (100%) rename api/_content/query/{98CVAb0zLR.1726174725311.json => cOxeB6k0CX.1727638383380.json} (98%) rename api/_content/query/{LcWrOc5HNX.1726174725311.json => lIKyXFs9L8.1727638383380.json} (99%) rename api/_content/query/{d7v45RMayO.1726174725311.json => ph6vNEpVOi.1727638383380.json} (99%) rename api/_content/query/{ucEXmLbw2Z.1726174725311.json => wVY7dvWXwt.1727638383380.json} (98%) rename api/_content/query/{v3HQ7aAWkW.1726174725311.json => x8mzqct7Ta.1727638383380.json} (99%) diff --git a/200.html b/200.html index 27d0f7d9..7d9f547c 100644 --- a/200.html +++ b/200.html @@ -1,9 +1,9 @@ - - - - - -
- \ No newline at end of file + + + + + +
+ \ No newline at end of file diff --git a/404.html b/404.html index 27d0f7d9..7d9f547c 100644 --- a/404.html +++ b/404.html @@ -1,9 +1,9 @@ - - - - - -
- \ No newline at end of file + + + + + +
+ \ No newline at end of file diff --git a/_nuxt/-GjkDpfn.js b/_nuxt/-GjkDpfn.js new file mode 100644 index 00000000..1935a85b --- /dev/null +++ b/_nuxt/-GjkDpfn.js @@ -0,0 +1 @@ +import{d as p,J as m,k as A,L as l,a0 as w}from"./K1dcBiIN.js";const S=["p","h1","h2","h3","h4","h5","h6","li"];function f(r,t){return r.type===t||typeof r.type=="object"&&r.type.tag===t||r.tag===t}function s(r){return f(r,"text")||f(r,Symbol.for("v-txt"))}function y(r){var t;return Array.isArray(r.children)||typeof r.children=="string"?r.children:typeof((t=r.children)==null?void 0:t.default)=="function"?r.children.default():[]}function a(r){if(!r)return"";if(Array.isArray(r))return r.map(a).join("");if(s(r))return r.children||r.value||"";const t=y(r);return Array.isArray(t)?t.map(a).filter(Boolean).join(""):""}function c(r,t=[]){if(Array.isArray(r))return r.flatMap(n=>c(n,t));let e=r;return t.some(n=>n==="*"||f(r,n))&&(e=y(r)||r,!Array.isArray(e)&&S.some(n=>f(r,n))&&(e=[e])),e}function h(r,t=[]){return r=Array.isArray(r)?r:[r],t.length?r.flatMap(e=>h(c(e,[t[0]]),t.slice(1))).filter(e=>!(s(e)&&a(e).trim()==="")):r}function g(r,t=[]){return typeof t=="string"&&(t=t.split(",").map(e=>e.trim()).filter(Boolean)),t.length?h(r,t).reduce((e,n)=>(s(n)?typeof e[e.length-1]=="string"?e[e.length-1]+=n.children:e.push(n.children):e.push(n),e),[]):r}const C=p({name:"MDCSlot",functional:!0,props:{name:{type:String,default:"default"},unwrap:{type:[Boolean,String],default:!1},use:{type:Function,default:void 0}},setup(r){const{parent:t}=w(),{default:e}=m(),n=A(()=>typeof r.unwrap=="string"?r.unwrap.split(" "):["*"]);return{fallbackSlot:e,tags:n,parent:t}},render({use:r,unwrap:t,fallbackSlot:e,tags:n,parent:i}){var o;try{let u=r;return typeof r=="string"&&(u=(i==null?void 0:i.slots[r])||((o=i==null?void 0:i.parent)==null?void 0:o.slots[r]),console.warn(`Please set :use="$slots.${r}" in component to enable reactivity`)),u?t?g(u(),n):[u()]:e?e():l("div")}catch{return l("div")}}}),_=p({props:{use:{type:Function,default:void 0},unwrap:{type:[Boolean,String],default:!1}},render(r){return l(C,r)}});export{_ as default}; diff --git a/_nuxt/36DYiIQe.js b/_nuxt/36DYiIQe.js deleted file mode 100644 index 52d9102b..00000000 --- a/_nuxt/36DYiIQe.js +++ /dev/null @@ -1 +0,0 @@ -import{a6 as _,U as T,ac as W,I as M,Q as J,O as H}from"./CZZfhpmp.js";import{g as k,a as j,b as O,o as b,c as G,d as $,f as P,h as D,i as Z}from"./CmpoAw97.js";import{p as q}from"./C-v3KzvZ.js";import{u as N}from"./B2jTtLqC.js";import"./DvDH6DOc.js";const F="memory",V=()=>{const t=new Map;return{name:F,getInstance:()=>t,hasItem(r){return t.has(r)},getItem(r){return t.get(r)??null},getItemRaw(r){return t.get(r)??null},setItem(r,n){t.set(r,n)},setItemRaw(r,n){t.set(r,n)},removeItem(r){t.delete(r)},getKeys(){return[...t.keys()]},clear(){t.clear()},dispose(){t.clear()}}};function Q(t){return!t||typeof t.then!="function"?Promise.resolve(t):t}function p(t,...r){try{return Q(t(...r))}catch(n){return Promise.reject(n)}}function X(t){const r=typeof t;return t===null||r!=="object"&&r!=="function"}function ee(t){const r=Object.getPrototypeOf(t);return!r||r.isPrototypeOf(Object)}function S(t){if(X(t))return String(t);if(ee(t)||Array.isArray(t))return JSON.stringify(t);if(typeof t.toJSON=="function")return S(t.toJSON());throw new Error("[unstorage] Cannot stringify value!")}function z(){if(typeof Buffer>"u")throw new TypeError("[unstorage] Buffer is not supported!")}const R="base64:";function te(t){if(typeof t=="string")return t;z();const r=Buffer.from(t).toString("base64");return R+r}function re(t){return typeof t!="string"||!t.startsWith(R)?t:(z(),Buffer.from(t.slice(R.length),"base64"))}const ne=["hasItem","getItem","getItemRaw","setItem","setItemRaw","removeItem","getMeta","setMeta","removeMeta","getKeys","clear","mount","unmount"];function ie(t,r){if(r=E(r),!r)return t;const n={...t};for(const a of ne)n[a]=(c="",...l)=>t[a](r+c,...l);return n.getKeys=(a="",...c)=>t.getKeys(r+a,...c).then(l=>l.map(o=>o.slice(r.length))),n}function y(t){return t?t.split("?")[0].replace(/[/\\]/g,":").replace(/:+/g,":").replace(/^:|:$/g,""):""}function ae(...t){return y(t.join(":"))}function E(t){return t=y(t),t?t+":":""}const se="memory",oe=()=>{const t=new Map;return{name:se,getInstance:()=>t,hasItem(r){return t.has(r)},getItem(r){return t.get(r)??null},getItemRaw(r){return t.get(r)??null},setItem(r,n){t.set(r,n)},setItemRaw(r,n){t.set(r,n)},removeItem(r){t.delete(r)},getKeys(){return[...t.keys()]},clear(){t.clear()},dispose(){t.clear()}}};function ue(t={}){const r={mounts:{"":t.driver||oe()},mountpoints:[""],watching:!1,watchListeners:[],unwatch:{}},n=e=>{for(const i of r.mountpoints)if(e.startsWith(i))return{base:i,relativeKey:e.slice(i.length),driver:r.mounts[i]};return{base:"",relativeKey:e,driver:r.mounts[""]}},a=(e,i)=>r.mountpoints.filter(s=>s.startsWith(e)||i&&e.startsWith(s)).map(s=>({relativeBase:e.length>s.length?e.slice(s.length):void 0,mountpoint:s,driver:r.mounts[s]})),c=(e,i)=>{if(r.watching){i=y(i);for(const s of r.watchListeners)s(e,i)}},l=async()=>{if(!r.watching){r.watching=!0;for(const e in r.mounts)r.unwatch[e]=await x(r.mounts[e],c,e)}},o=async()=>{if(r.watching){for(const e in r.unwatch)await r.unwatch[e]();r.unwatch={},r.watching=!1}},g=(e,i,s)=>{const u=new Map,m=f=>{let d=u.get(f.base);return d||(d={driver:f.driver,base:f.base,items:[]},u.set(f.base,d)),d};for(const f of e){const d=typeof f=="string",v=y(d?f:f.key),I=d?void 0:f.value,w=d||!f.options?i:{...i,...f.options},A=n(v);m(A).items.push({key:v,value:I,relativeKey:A.relativeKey,options:w})}return Promise.all([...u.values()].map(f=>s(f))).then(f=>f.flat())},h={hasItem(e,i={}){e=y(e);const{relativeKey:s,driver:u}=n(e);return p(u.hasItem,s,i)},getItem(e,i={}){e=y(e);const{relativeKey:s,driver:u}=n(e);return p(u.getItem,s,i).then(m=>_(m))},getItems(e,i){return g(e,i,s=>s.driver.getItems?p(s.driver.getItems,s.items.map(u=>({key:u.relativeKey,options:u.options})),i).then(u=>u.map(m=>({key:ae(s.base,m.key),value:_(m.value)}))):Promise.all(s.items.map(u=>p(s.driver.getItem,u.relativeKey,u.options).then(m=>({key:u.key,value:_(m)})))))},getItemRaw(e,i={}){e=y(e);const{relativeKey:s,driver:u}=n(e);return u.getItemRaw?p(u.getItemRaw,s,i):p(u.getItem,s,i).then(m=>re(m))},async setItem(e,i,s={}){if(i===void 0)return h.removeItem(e);e=y(e);const{relativeKey:u,driver:m}=n(e);m.setItem&&(await p(m.setItem,u,S(i),s),m.watch||c("update",e))},async setItems(e,i){await g(e,i,async s=>{if(s.driver.setItems)return p(s.driver.setItems,s.items.map(u=>({key:u.relativeKey,value:S(u.value),options:u.options})),i);s.driver.setItem&&await Promise.all(s.items.map(u=>p(s.driver.setItem,u.relativeKey,S(u.value),u.options)))})},async setItemRaw(e,i,s={}){if(i===void 0)return h.removeItem(e,s);e=y(e);const{relativeKey:u,driver:m}=n(e);if(m.setItemRaw)await p(m.setItemRaw,u,i,s);else if(m.setItem)await p(m.setItem,u,te(i),s);else return;m.watch||c("update",e)},async removeItem(e,i={}){typeof i=="boolean"&&(i={removeMeta:i}),e=y(e);const{relativeKey:s,driver:u}=n(e);u.removeItem&&(await p(u.removeItem,s,i),(i.removeMeta||i.removeMata)&&await p(u.removeItem,s+"$",i),u.watch||c("remove",e))},async getMeta(e,i={}){typeof i=="boolean"&&(i={nativeOnly:i}),e=y(e);const{relativeKey:s,driver:u}=n(e),m=Object.create(null);if(u.getMeta&&Object.assign(m,await p(u.getMeta,s,i)),!i.nativeOnly){const f=await p(u.getItem,s+"$",i).then(d=>_(d));f&&typeof f=="object"&&(typeof f.atime=="string"&&(f.atime=new Date(f.atime)),typeof f.mtime=="string"&&(f.mtime=new Date(f.mtime)),Object.assign(m,f))}return m},setMeta(e,i,s={}){return this.setItem(e+"$",i,s)},removeMeta(e,i={}){return this.removeItem(e+"$",i)},async getKeys(e,i={}){e=E(e);const s=a(e,!0);let u=[];const m=[];for(const f of s){const d=await p(f.driver.getKeys,f.relativeBase,i);for(const v of d){const I=f.mountpoint+y(v);u.some(w=>I.startsWith(w))||m.push(I)}u=[f.mountpoint,...u.filter(v=>!v.startsWith(f.mountpoint))]}return e?m.filter(f=>f.startsWith(e)&&f[f.length-1]!=="$"):m.filter(f=>f[f.length-1]!=="$")},async clear(e,i={}){e=E(e),await Promise.all(a(e,!1).map(async s=>{if(s.driver.clear)return p(s.driver.clear,s.relativeBase,i);if(s.driver.removeItem){const u=await s.driver.getKeys(s.relativeBase||"",i);return Promise.all(u.map(m=>s.driver.removeItem(m,i)))}}))},async dispose(){await Promise.all(Object.values(r.mounts).map(e=>L(e)))},async watch(e){return await l(),r.watchListeners.push(e),async()=>{r.watchListeners=r.watchListeners.filter(i=>i!==e),r.watchListeners.length===0&&await o()}},async unwatch(){r.watchListeners=[],await o()},mount(e,i){if(e=E(e),e&&r.mounts[e])throw new Error(`already mounted at ${e}`);return e&&(r.mountpoints.push(e),r.mountpoints.sort((s,u)=>u.length-s.length)),r.mounts[e]=i,r.watching&&Promise.resolve(x(i,c,e)).then(s=>{r.unwatch[e]=s}).catch(console.error),h},async unmount(e,i=!0){e=E(e),!(!e||!r.mounts[e])&&(r.watching&&e in r.unwatch&&(r.unwatch[e](),delete r.unwatch[e]),i&&await L(r.mounts[e]),r.mountpoints=r.mountpoints.filter(s=>s!==e),delete r.mounts[e])},getMount(e=""){e=y(e)+":";const i=n(e);return{driver:i.driver,base:i.base}},getMounts(e="",i={}){return e=y(e),a(e,i.parents).map(u=>({driver:u.driver,base:u.mountpoint}))},keys:(e,i={})=>h.getKeys(e,i),get:(e,i={})=>h.getItem(e,i),set:(e,i,s={})=>h.setItem(e,i,s),has:(e,i={})=>h.hasItem(e,i),del:(e,i={})=>h.removeItem(e,i),remove:(e,i={})=>h.removeItem(e,i)};return h}function x(t,r,n){return t.watch?t.watch((a,c)=>r(a,n+c)):()=>{}}async function L(t){typeof t.dispose=="function"&&await p(t.dispose)}function ce(t={}){const r=le(n,t.operators);function n(a,c){return typeof c!="object"||c instanceof RegExp?r.$eq(a,c):Object.keys(c||{}).every(l=>{const o=c[l];if(l.startsWith("$")&&r[l]){const g=r[l];return typeof g=="function"?g(a,o):!1}return n(k(a,l),o)})}return n}function le(t,r={}){return{$match:(n,a)=>t(n,a),$eq:(n,a)=>a instanceof RegExp?a.test(n):n===a,$ne:(n,a)=>a instanceof RegExp?!a.test(n):n!==a,$not:(n,a)=>!t(n,a),$and:(n,a)=>(j(a,"$and requires an array as condition"),a.every(c=>t(n,c))),$or:(n,a)=>(j(a,"$or requires an array as condition"),a.some(c=>t(n,c))),$in:(n,a)=>O(a).some(c=>Array.isArray(n)?t(n,{$contains:c}):t(n,c)),$contains:(n,a)=>(n=Array.isArray(n)?n:String(n),O(a).every(c=>n.includes(c))),$icontains:(n,a)=>{if(typeof a!="string")throw new TypeError("$icontains requires a string, use $contains instead");return n=String(n).toLocaleLowerCase(),O(a).every(c=>n.includes(c.toLocaleLowerCase()))},$containsAny:(n,a)=>(j(a,"$containsAny requires an array as condition"),n=Array.isArray(n)?n:String(n),a.some(c=>n.includes(c))),$exists:(n,a)=>a?typeof n<"u":typeof n>"u",$type:(n,a)=>typeof n===String(a),$regex:(n,a)=>{if(!(a instanceof RegExp)){const c=String(a).match(/\/(.*)\/([dgimsuy]*)$/);a=c!=null&&c[1]?new RegExp(c[1],c[2]||""):new RegExp(a)}return a.test(String(n||""))},$lt:(n,a)=>nn<=a,$gt:(n,a)=>n>a,$gte:(n,a)=>n>=a,...r||{}}}function fe(t){const r=ce(),n=(l,{query:o,before:g,after:h})=>{const e=typeof o=="string"?{_path:o}:o,i=l.findIndex(u=>r(u,e));g=g??1,h=h??1;const s=new Array(g+h).fill(null,0);return i===-1?s:s.map((u,m)=>l[i-g+m+ +(m>=g)]||null)},a=[(l,o)=>{const g=l.result.filter(h=>O(o.where).every(e=>r(h,e)));return{...l,result:g,total:g.length}},(l,o)=>O(o.sort).forEach(g=>G(l.result,g)),function(o,g,h){var e;if(g.surround){let i=n(((e=o.result)==null?void 0:e.length)===1?h:o.result,g.surround);i=$(P(g.without))(i),i=$(D(g.only))(i),o.surround=i}return o}],c=[(l,o)=>{if(o.skip)return{...l,result:l.result.slice(o.skip),skip:o.skip}},(l,o)=>{if(o.limit)return{...l,result:l.result.slice(0,o.limit),limit:o.limit}},function(o,g,h){var e,i,s;if(g.dirConfig){const u=((e=o.result[0])==null?void 0:e._path)||((s=(i=g.where)==null?void 0:i.find(m=>m._path))==null?void 0:s._path);if(typeof u=="string"){const m=h.find(f=>f._path===T(u,"_dir"));m&&(o.dirConfig={_path:m._path,...P(["_"])(m)})}}return o},(l,o)=>({...l,result:$(P(o.without))(l.result)}),(l,o)=>({...l,result:$(D(o.only))(l.result)})];return async l=>{const o=await t(),g=l.params(),h={result:o,limit:0,skip:0,total:o.length},e=a.reduce((s,u)=>u(s,g,o)||s,h);if(g.count)return{result:e.result.length};const i=c.reduce((s,u)=>u(s,g,o)||s,e);return g.first?{...b(["skip","limit","total"])(i),result:i.result[0]}:i}}function U(t){const r=fe(t);return async n=>{var l;n.params().first&&n.withDirConfig();const a=n.params(),c=await r(n);return a.surround?c==null?void 0:c.surround:(c!=null&&c.dirConfig&&(c.result={_path:(l=c.dirConfig)==null?void 0:l._path,...c.result,_dir:c.dirConfig}),c==null?void 0:c.result)}}var me={exports:{}};(function(t,r){(function(n,a,c){t.exports=c(),t.exports.default=c()})("slugify",W,function(){var n=JSON.parse(`{"$":"dollar","%":"percent","&":"and","<":"less",">":"greater","|":"or","¢":"cent","£":"pound","¤":"currency","¥":"yen","©":"(c)","ª":"a","®":"(r)","º":"o","À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","Æ":"AE","Ç":"C","È":"E","É":"E","Ê":"E","Ë":"E","Ì":"I","Í":"I","Î":"I","Ï":"I","Ð":"D","Ñ":"N","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","Ù":"U","Ú":"U","Û":"U","Ü":"U","Ý":"Y","Þ":"TH","ß":"ss","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","æ":"ae","ç":"c","è":"e","é":"e","ê":"e","ë":"e","ì":"i","í":"i","î":"i","ï":"i","ð":"d","ñ":"n","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","ù":"u","ú":"u","û":"u","ü":"u","ý":"y","þ":"th","ÿ":"y","Ā":"A","ā":"a","Ă":"A","ă":"a","Ą":"A","ą":"a","Ć":"C","ć":"c","Č":"C","č":"c","Ď":"D","ď":"d","Đ":"DJ","đ":"dj","Ē":"E","ē":"e","Ė":"E","ė":"e","Ę":"e","ę":"e","Ě":"E","ě":"e","Ğ":"G","ğ":"g","Ģ":"G","ģ":"g","Ĩ":"I","ĩ":"i","Ī":"i","ī":"i","Į":"I","į":"i","İ":"I","ı":"i","Ķ":"k","ķ":"k","Ļ":"L","ļ":"l","Ľ":"L","ľ":"l","Ł":"L","ł":"l","Ń":"N","ń":"n","Ņ":"N","ņ":"n","Ň":"N","ň":"n","Ō":"O","ō":"o","Ő":"O","ő":"o","Œ":"OE","œ":"oe","Ŕ":"R","ŕ":"r","Ř":"R","ř":"r","Ś":"S","ś":"s","Ş":"S","ş":"s","Š":"S","š":"s","Ţ":"T","ţ":"t","Ť":"T","ť":"t","Ũ":"U","ũ":"u","Ū":"u","ū":"u","Ů":"U","ů":"u","Ű":"U","ű":"u","Ų":"U","ų":"u","Ŵ":"W","ŵ":"w","Ŷ":"Y","ŷ":"y","Ÿ":"Y","Ź":"Z","ź":"z","Ż":"Z","ż":"z","Ž":"Z","ž":"z","Ə":"E","ƒ":"f","Ơ":"O","ơ":"o","Ư":"U","ư":"u","Lj":"LJ","lj":"lj","Nj":"NJ","nj":"nj","Ș":"S","ș":"s","Ț":"T","ț":"t","ə":"e","˚":"o","Ά":"A","Έ":"E","Ή":"H","Ί":"I","Ό":"O","Ύ":"Y","Ώ":"W","ΐ":"i","Α":"A","Β":"B","Γ":"G","Δ":"D","Ε":"E","Ζ":"Z","Η":"H","Θ":"8","Ι":"I","Κ":"K","Λ":"L","Μ":"M","Ν":"N","Ξ":"3","Ο":"O","Π":"P","Ρ":"R","Σ":"S","Τ":"T","Υ":"Y","Φ":"F","Χ":"X","Ψ":"PS","Ω":"W","Ϊ":"I","Ϋ":"Y","ά":"a","έ":"e","ή":"h","ί":"i","ΰ":"y","α":"a","β":"b","γ":"g","δ":"d","ε":"e","ζ":"z","η":"h","θ":"8","ι":"i","κ":"k","λ":"l","μ":"m","ν":"n","ξ":"3","ο":"o","π":"p","ρ":"r","ς":"s","σ":"s","τ":"t","υ":"y","φ":"f","χ":"x","ψ":"ps","ω":"w","ϊ":"i","ϋ":"y","ό":"o","ύ":"y","ώ":"w","Ё":"Yo","Ђ":"DJ","Є":"Ye","І":"I","Ї":"Yi","Ј":"J","Љ":"LJ","Њ":"NJ","Ћ":"C","Џ":"DZ","А":"A","Б":"B","В":"V","Г":"G","Д":"D","Е":"E","Ж":"Zh","З":"Z","И":"I","Й":"J","К":"K","Л":"L","М":"M","Н":"N","О":"O","П":"P","Р":"R","С":"S","Т":"T","У":"U","Ф":"F","Х":"H","Ц":"C","Ч":"Ch","Ш":"Sh","Щ":"Sh","Ъ":"U","Ы":"Y","Ь":"","Э":"E","Ю":"Yu","Я":"Ya","а":"a","б":"b","в":"v","г":"g","д":"d","е":"e","ж":"zh","з":"z","и":"i","й":"j","к":"k","л":"l","м":"m","н":"n","о":"o","п":"p","р":"r","с":"s","т":"t","у":"u","ф":"f","х":"h","ц":"c","ч":"ch","ш":"sh","щ":"sh","ъ":"u","ы":"y","ь":"","э":"e","ю":"yu","я":"ya","ё":"yo","ђ":"dj","є":"ye","і":"i","ї":"yi","ј":"j","љ":"lj","њ":"nj","ћ":"c","ѝ":"u","џ":"dz","Ґ":"G","ґ":"g","Ғ":"GH","ғ":"gh","Қ":"KH","қ":"kh","Ң":"NG","ң":"ng","Ү":"UE","ү":"ue","Ұ":"U","ұ":"u","Һ":"H","һ":"h","Ә":"AE","ә":"ae","Ө":"OE","ө":"oe","Ա":"A","Բ":"B","Գ":"G","Դ":"D","Ե":"E","Զ":"Z","Է":"E'","Ը":"Y'","Թ":"T'","Ժ":"JH","Ի":"I","Լ":"L","Խ":"X","Ծ":"C'","Կ":"K","Հ":"H","Ձ":"D'","Ղ":"GH","Ճ":"TW","Մ":"M","Յ":"Y","Ն":"N","Շ":"SH","Չ":"CH","Պ":"P","Ջ":"J","Ռ":"R'","Ս":"S","Վ":"V","Տ":"T","Ր":"R","Ց":"C","Փ":"P'","Ք":"Q'","Օ":"O''","Ֆ":"F","և":"EV","ء":"a","آ":"aa","أ":"a","ؤ":"u","إ":"i","ئ":"e","ا":"a","ب":"b","ة":"h","ت":"t","ث":"th","ج":"j","ح":"h","خ":"kh","د":"d","ذ":"th","ر":"r","ز":"z","س":"s","ش":"sh","ص":"s","ض":"dh","ط":"t","ظ":"z","ع":"a","غ":"gh","ف":"f","ق":"q","ك":"k","ل":"l","م":"m","ن":"n","ه":"h","و":"w","ى":"a","ي":"y","ً":"an","ٌ":"on","ٍ":"en","َ":"a","ُ":"u","ِ":"e","ْ":"","٠":"0","١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","پ":"p","چ":"ch","ژ":"zh","ک":"k","گ":"g","ی":"y","۰":"0","۱":"1","۲":"2","۳":"3","۴":"4","۵":"5","۶":"6","۷":"7","۸":"8","۹":"9","฿":"baht","ა":"a","ბ":"b","გ":"g","დ":"d","ე":"e","ვ":"v","ზ":"z","თ":"t","ი":"i","კ":"k","ლ":"l","მ":"m","ნ":"n","ო":"o","პ":"p","ჟ":"zh","რ":"r","ს":"s","ტ":"t","უ":"u","ფ":"f","ქ":"k","ღ":"gh","ყ":"q","შ":"sh","ჩ":"ch","ც":"ts","ძ":"dz","წ":"ts","ჭ":"ch","ხ":"kh","ჯ":"j","ჰ":"h","Ṣ":"S","ṣ":"s","Ẁ":"W","ẁ":"w","Ẃ":"W","ẃ":"w","Ẅ":"W","ẅ":"w","ẞ":"SS","Ạ":"A","ạ":"a","Ả":"A","ả":"a","Ấ":"A","ấ":"a","Ầ":"A","ầ":"a","Ẩ":"A","ẩ":"a","Ẫ":"A","ẫ":"a","Ậ":"A","ậ":"a","Ắ":"A","ắ":"a","Ằ":"A","ằ":"a","Ẳ":"A","ẳ":"a","Ẵ":"A","ẵ":"a","Ặ":"A","ặ":"a","Ẹ":"E","ẹ":"e","Ẻ":"E","ẻ":"e","Ẽ":"E","ẽ":"e","Ế":"E","ế":"e","Ề":"E","ề":"e","Ể":"E","ể":"e","Ễ":"E","ễ":"e","Ệ":"E","ệ":"e","Ỉ":"I","ỉ":"i","Ị":"I","ị":"i","Ọ":"O","ọ":"o","Ỏ":"O","ỏ":"o","Ố":"O","ố":"o","Ồ":"O","ồ":"o","Ổ":"O","ổ":"o","Ỗ":"O","ỗ":"o","Ộ":"O","ộ":"o","Ớ":"O","ớ":"o","Ờ":"O","ờ":"o","Ở":"O","ở":"o","Ỡ":"O","ỡ":"o","Ợ":"O","ợ":"o","Ụ":"U","ụ":"u","Ủ":"U","ủ":"u","Ứ":"U","ứ":"u","Ừ":"U","ừ":"u","Ử":"U","ử":"u","Ữ":"U","ữ":"u","Ự":"U","ự":"u","Ỳ":"Y","ỳ":"y","Ỵ":"Y","ỵ":"y","Ỷ":"Y","ỷ":"y","Ỹ":"Y","ỹ":"y","–":"-","‘":"'","’":"'","“":"\\"","”":"\\"","„":"\\"","†":"+","•":"*","…":"...","₠":"ecu","₢":"cruzeiro","₣":"french franc","₤":"lira","₥":"mill","₦":"naira","₧":"peseta","₨":"rupee","₩":"won","₪":"new shequel","₫":"dong","€":"euro","₭":"kip","₮":"tugrik","₯":"drachma","₰":"penny","₱":"peso","₲":"guarani","₳":"austral","₴":"hryvnia","₵":"cedi","₸":"kazakhstani tenge","₹":"indian rupee","₺":"turkish lira","₽":"russian ruble","₿":"bitcoin","℠":"sm","™":"tm","∂":"d","∆":"delta","∑":"sum","∞":"infinity","♥":"love","元":"yuan","円":"yen","﷼":"rial","ﻵ":"laa","ﻷ":"laa","ﻹ":"lai","ﻻ":"la"}`),a=JSON.parse('{"bg":{"Й":"Y","Ц":"Ts","Щ":"Sht","Ъ":"A","Ь":"Y","й":"y","ц":"ts","щ":"sht","ъ":"a","ь":"y"},"de":{"Ä":"AE","ä":"ae","Ö":"OE","ö":"oe","Ü":"UE","ü":"ue","ß":"ss","%":"prozent","&":"und","|":"oder","∑":"summe","∞":"unendlich","♥":"liebe"},"es":{"%":"por ciento","&":"y","<":"menor que",">":"mayor que","|":"o","¢":"centavos","£":"libras","¤":"moneda","₣":"francos","∑":"suma","∞":"infinito","♥":"amor"},"fr":{"%":"pourcent","&":"et","<":"plus petit",">":"plus grand","|":"ou","¢":"centime","£":"livre","¤":"devise","₣":"franc","∑":"somme","∞":"infini","♥":"amour"},"pt":{"%":"porcento","&":"e","<":"menor",">":"maior","|":"ou","¢":"centavo","∑":"soma","£":"libra","∞":"infinito","♥":"amor"},"uk":{"И":"Y","и":"y","Й":"Y","й":"y","Ц":"Ts","ц":"ts","Х":"Kh","х":"kh","Щ":"Shch","щ":"shch","Г":"H","г":"h"},"vi":{"Đ":"D","đ":"d"},"da":{"Ø":"OE","ø":"oe","Å":"AA","å":"aa","%":"procent","&":"og","|":"eller","$":"dollar","<":"mindre end",">":"større end"},"nb":{"&":"og","Å":"AA","Æ":"AE","Ø":"OE","å":"aa","æ":"ae","ø":"oe"},"it":{"&":"e"},"nl":{"&":"en"},"sv":{"&":"och","Å":"AA","Ä":"AE","Ö":"OE","å":"aa","ä":"ae","ö":"oe"}}');function c(l,o){if(typeof l!="string")throw new Error("slugify: string argument expected");o=typeof o=="string"?{replacement:o}:o||{};var g=a[o.locale]||{},h=o.replacement===void 0?"-":o.replacement,e=o.trim===void 0?!0:o.trim,i=l.normalize().split("").reduce(function(s,u){var m=g[u];return m===void 0&&(m=n[u]),m===void 0&&(m=u),m===h&&(m=" "),s+m.replace(o.remove||/[^\w\s$*_+~.()'"!\-:@]+/g,"")},"");return o.strict&&(i=i.replace(/[^A-Za-z0-9\s]/g,"")),e&&(i=i.trim()),i=i.replace(/\s+/g,h),o.lower&&(i=i.toLowerCase()),i}return c.extend=function(l){Object.assign(n,l)},c})})(me);const he=t=>t.split(/[\s-]/g).map(q).join(" ");function ge(t,r){const{navigation:n}=M().public.content;if(n===!1)return[];const a=l=>({...de(["title",...n.fields])(l),...ye(l==null?void 0:l.navigation)?l.navigation:{}}),c=t.sort((l,o)=>l._path.localeCompare(o._path)).reduce((l,o)=>{var m;const g=o._path.substring(1).split("/"),h=o._id.split(":").slice(1),e=!!((m=h[h.length-1])!=null&&m.match(/([1-9][0-9]*\.)?index.md/g)),i=f=>({title:f.title,_path:f._path,_file:f._file,children:[],...a(f),...f._draft?{_draft:!0}:{}}),s=i(o);if(e){const f=r[s._path];if(typeof(f==null?void 0:f.navigation)<"u"&&!(f!=null&&f.navigation))return l;if(o._path!=="/"){const d=i(o);s.children.push(d)}f&&Object.assign(s,a(f))}return g.length===1?(l.push(s),l):(g.slice(0,-1).reduce((f,d,v)=>{const I="/"+g.slice(0,v+1).join("/"),w=r[I];if(typeof(w==null?void 0:w.navigation)<"u"&&!w.navigation)return[];let A=f.find(B=>B._path===I);return A||(A={title:he(d),_path:I,_file:o._file,children:[],...w&&a(w)},f.push(A)),A.children},l).push(s),l)},[]);return Y(c)}const pe=new Intl.Collator(void 0,{numeric:!0,sensitivity:"base"});function Y(t){var n;t.forEach(a=>{a._file=a._file.split(".").slice(0,-1).join(".")});const r=t.sort((a,c)=>pe.compare(a._file,c._file));for(const a of r)(n=a.children)!=null&&n.length?Y(a.children):delete a.children,delete a._file;return t}function de(t){return r=>(r=r||{},t&&t.length?t.filter(n=>typeof r[n]<"u").reduce((n,a)=>Object.assign(n,{[a]:r[a]}),{}):r)}function ye(t){return Object.prototype.toString.call(t)==="[object Object]"}const we=t=>J(t,M().public.content.api.baseURL),ve=ie(ue({driver:V()}),"@content");function Ie(t){async function r(){const n=new Set(await t.getKeys("cache:")),a=N().getPreviewToken();if(a){const l=await t.getItem(`${a}$`).then(h=>h||{});if(Array.isArray(l.ignoreSources)){const h=l.ignoreSources.map(e=>`cache:${e.trim()}:`);for(const e of n)h.some(i=>e.startsWith(i))&&n.delete(e)}const o=await t.getKeys(`${a}:`),g=await Promise.all(o.map(h=>t.getItem(h)));for(const h of g)n.delete(`cache:${h._id}`),h.__deleted||n.add(`${a}:${h._id}`)}return await Promise.all(Array.from(n).map(l=>t.getItem(l)))}return{storage:t,fetch:U(r),query:n=>Z(U(r),{initialParams:n,legacy:!0})}}let C=null,K=null;async function Ae(){return K?await K:C||(K=Ee(),C=await K),C}async function Ee(){const t=H(),{content:r}=M().public,n=Ie(ve),a=await n.storage.getItem("integrity");if(r.integrity!==+(a||0)){const{contents:c,navigation:l}=await $fetch(we(r.integrity?`cache.${r.integrity}.json`:"cache.json"));await Promise.all(c.map(o=>n.storage.setItem(`cache:${o._id}`,o))),await n.storage.setItem("navigation",l),await n.storage.setItem("integrity",r.integrity)}return await t.callHook("content:storage",n.storage),n}async function je(t){const r=await Ae();if(!N().getPreviewToken()&&Object.keys(t||{}).length===0)return r.storage.getItem("navigation");const n=await r.query(t).where({_partial:!1,navigation:{$ne:!1}}).find(),c=(await r.query().where({_path:/\/_dir$/i,_partial:!0}).find()).reduce((l,o)=>{var h;((h=o.title)==null?void 0:h.toLowerCase())==="dir"&&(o.title=void 0);const g=o._path.split("/").slice(0,-1).join("/")||"/";return l[g]={...o,...o.body},l},{});return ge(n,c)}export{ve as contentStorage,Ie as createDB,je as generateNavigation,Ae as useContentDatabase}; diff --git a/_nuxt/3aFKPIgF.js b/_nuxt/3aFKPIgF.js deleted file mode 100644 index 23a6516e..00000000 --- a/_nuxt/3aFKPIgF.js +++ /dev/null @@ -1 +0,0 @@ -import{f as i}from"./Dnd51l0P.js";import{d as u,J as f,k as c,L as a,a0 as d}from"./CZZfhpmp.js";const p=u({name:"MDCSlot",functional:!0,props:{name:{type:String,default:"default"},unwrap:{type:[Boolean,String],default:!1},use:{type:Function,default:void 0}},setup(t){const{parent:s}=d(),{default:o}=f(),r=c(()=>typeof t.unwrap=="string"?t.unwrap.split(" "):["*"]);return{fallbackSlot:o,tags:r,parent:s}},render({use:t,unwrap:s,fallbackSlot:o,tags:r,parent:e}){var l;try{let n=t;return typeof t=="string"&&(n=(e==null?void 0:e.slots[t])||((l=e==null?void 0:e.parent)==null?void 0:l.slots[t]),console.warn(`Please set :use="$slots.${t}" in component to enable reactivity`)),n?s?i(n(),r):[n()]:o?o():a("div")}catch{return a("div")}}}),g=u({props:{use:{type:Function,default:void 0},unwrap:{type:[Boolean,String],default:!1}},render(t){return a(p,t)}});export{g as default}; diff --git a/_nuxt/4KDx6Qdh.js b/_nuxt/4KDx6Qdh.js new file mode 100644 index 00000000..22177a97 --- /dev/null +++ b/_nuxt/4KDx6Qdh.js @@ -0,0 +1 @@ +import{d as r,k as n,R as c,K as h,I as o,U as d,o as l,c as u,a as f}from"./K1dcBiIN.js";const g=["src","alt","width","height"],p=r({__name:"ProseImg",props:{src:{type:String,default:""},alt:{type:String,default:""},width:{type:[String,Number],default:void 0},height:{type:[String,Number],default:void 0}},setup(e){const t=e,i=n(()=>{var a;if((a=t.src)!=null&&a.startsWith("/")&&!t.src.startsWith("//")){const s=c(h(o().app.baseURL));if(s!=="/"&&!t.src.startsWith(s))return d(s,t.src)}return t.src});return(a,s)=>(l(),u("img",{src:f(i),alt:e.alt,width:e.width,height:e.height},null,8,g))}});export{p as default}; diff --git a/_nuxt/DRhtvB_q.js b/_nuxt/4ZR8vDGy.js similarity index 63% rename from _nuxt/DRhtvB_q.js rename to _nuxt/4ZR8vDGy.js index 81ebf1f4..4cd01ded 100644 --- a/_nuxt/DRhtvB_q.js +++ b/_nuxt/4ZR8vDGy.js @@ -1 +1 @@ -import{m as r,o,c as t,a8 as s}from"./CZZfhpmp.js";const c={};function n(e,a){return o(),t("tr",null,[s(e.$slots,"default")])}const f=r(c,[["render",n]]);export{f as default}; +import{m as r,o,c as t,a8 as s}from"./K1dcBiIN.js";const c={};function n(e,a){return o(),t("tr",null,[s(e.$slots,"default")])}const f=r(c,[["render",n]]);export{f as default}; diff --git a/_nuxt/B09kizko.js b/_nuxt/B09kizko.js deleted file mode 100644 index b2f8c1ef..00000000 --- a/_nuxt/B09kizko.js +++ /dev/null @@ -1 +0,0 @@ -import{c as t,b as r,o}from"./CZZfhpmp.js";const a={class:"flex h-[1024px] justify-center border-2 border-gray-500"},i={__name:"conway",setup(s){return(n,e)=>(o(),t("main",a,e[0]||(e[0]=[r("iframe",{src:"https://cmpadden.github.io/conway/",width:"100%",height:"100%"},null,-1)])))}};export{i as default}; diff --git a/_nuxt/B16Ch1Rg.js b/_nuxt/B16Ch1Rg.js deleted file mode 100644 index d3f04e60..00000000 --- a/_nuxt/B16Ch1Rg.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as o}from"./CuOPeUWs.js";import"./CZZfhpmp.js";import"./C-v3KzvZ.js";import"./Dnd51l0P.js";import"./B2jTtLqC.js";import"./DvDH6DOc.js";export{o as default}; diff --git a/_nuxt/B1tmNyhF.js b/_nuxt/B1tmNyhF.js deleted file mode 100644 index 1dfc8b5c..00000000 --- a/_nuxt/B1tmNyhF.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as f}from"./CuOPeUWs.js";import{d as l,v as s,J as d,L as c}from"./CZZfhpmp.js";import"./C-v3KzvZ.js";import"./Dnd51l0P.js";import"./B2jTtLqC.js";import"./DvDH6DOc.js";const $=l({name:"ContentRenderer",props:{value:{type:Object,required:!1,default:()=>({})},excerpt:{type:Boolean,default:!1},tag:{type:String,default:"div"}},setup(t){s(()=>t.excerpt,n=>{var e,i,a;n&&!((e=t.value)!=null&&e.excerpt)&&(console.warn(`No excerpt found for document content/${(i=t==null?void 0:t.value)==null?void 0:i._path}.${(a=t==null?void 0:t.value)==null?void 0:a._extension}!`),console.warn("Make sure to use in your content if you want to use excerpt feature."))},{immediate:!0})},render(t){var u,o;const n=d(),{value:e,excerpt:i,tag:a}=t,r=i?e==null?void 0:e.excerpt:e==null?void 0:e.body;return!((u=r==null?void 0:r.children)!=null&&u.length)&&(n!=null&&n.empty)?n.empty({value:e,excerpt:i,tag:a,...this.$attrs}):n!=null&&n.default?n.default({value:e,excerpt:i,tag:a,...this.$attrs}):(r==null?void 0:r.type)==="root"&&((o=r==null?void 0:r.children)!=null&&o.length)?c(f,{value:e,excerpt:i,tag:a,...this.$attrs}):c("pre",null,JSON.stringify({message:"You should use slots with ",value:e,excerpt:i,tag:a},null,2))}});export{$ as default}; diff --git a/_nuxt/B2jTtLqC.js b/_nuxt/B2jTtLqC.js deleted file mode 100644 index b46b1e86..00000000 --- a/_nuxt/B2jTtLqC.js +++ /dev/null @@ -1 +0,0 @@ -import{j as S,a1 as T,Z as E,v as C,a7 as A,a6 as O,G as P,u as h}from"./CZZfhpmp.js";import{i as I}from"./DvDH6DOc.js";function R(e,o){if(typeof e!="string")throw new TypeError("argument str must be a string");const i={},t=o||{},a=t.decode||D;let s=0;for(;sO(decodeURIComponent(e)),encode:e=>encodeURIComponent(typeof e=="string"?e:JSON.stringify(e))},L=void 0;function y(e,o){var u;const i={...M,...o},t=b(i)||{};let a;i.maxAge!==void 0?a=i.maxAge*1e3:i.expires&&(a=i.expires.getTime()-Date.now());const s=a!==void 0&&a<=0,r=f(s?void 0:t[e]??((u=i.default)==null?void 0:u.call(i))),n=a&&!s?q(r,a,i.watch&&i.watch!=="shallow"):S(r);{let c=null;try{!L&&typeof BroadcastChannel<"u"&&(c=new BroadcastChannel(`nuxt:cookies:${e}`))}catch{}const l=()=>{i.readonly||I(n.value,t[e])||(_(e,n.value,i),t[e]=f(n.value),c==null||c.postMessage({value:i.encode(n.value)}))},p=w=>{var v;const j=w.refresh?(v=b(i))==null?void 0:v[e]:i.decode(w.value);d=!0,t[e]=n.value=j,P(()=>{d=!1})};let d=!1;T()&&E(()=>{d=!0,l(),c==null||c.close()}),c&&(c.onmessage=({data:w})=>p(w)),i.watch?C(n,()=>{d||l()},{deep:i.watch!=="shallow"}):l()}return n}function b(e={}){return R(document.cookie,e)}function U(e,o,i={}){return o==null?g(e,o,{...i,maxAge:-1}):g(e,o,i)}function _(e,o,i={}){document.cookie=U(e,o,i)}const k=2147483647;function q(e,o,i){let t,a,s=0;const r=i?S(e):{value:e};return T()&&E(()=>{a==null||a(),clearTimeout(t)}),A((n,u)=>{i&&(a=C(r,u));function c(){clearTimeout(t);const l=o-s,p=l{if(s+=p,s({isEnabled:()=>{const t=h().query;return Object.prototype.hasOwnProperty.call(t,"preview")&&!t.preview?!1:!!(t.preview||y("previewToken").value||sessionStorage.getItem("previewToken"))},getPreviewToken:()=>y("previewToken").value||sessionStorage.getItem("previewToken")||void 0,setPreviewToken:t=>{y("previewToken").value=t,h().query.preview=t||"",t?sessionStorage.setItem("previewToken",t):sessionStorage.removeItem("previewToken"),window.location.reload()}});export{V as u}; diff --git a/_nuxt/B44J2786.js b/_nuxt/B44J2786.js new file mode 100644 index 00000000..b23bdf72 --- /dev/null +++ b/_nuxt/B44J2786.js @@ -0,0 +1 @@ +import{m as u,c as _,o as m,b as c}from"./K1dcBiIN.js";const p={data(){return{}},mounted(){const s=["#FFBA08","#FAA307","#F48C06","#E85D04","#DC2F02","#D00000","#9D0208","#6A040F","#370617","#03071E"],a=e=>{const i=t=>e.unhex([t.slice(1,3),t.slice(3,5),t.slice(5,7)]),d=(t,r)=>t.map(n=>{const o=e.floor(n+e.random(-r,r));return o<0?0:o>255?255:o});e.setup=()=>{e.createCanvas(400,400),e.frameRate(5)},e.draw=()=>{e.background(0,0,0),e.noStroke(),e.noFill();const t=9,r=400/t;for(let n=0;n<=t;n++)for(let o=0;o<=t;o++){const f=s[o%9];e.fill(d(i(f),15)),e.square(n*r,o*r,r)}}};new this.$p5(a,"canvas")}},h={class:"bg-gradient-to-b from-green-800 to-gray-800"},v=c("div",{class:"grid h-screen place-items-center"},[c("div",{class:"font-mono text-white"},[c("div",{class:"mb-2 border-2 border-white"},[c("div",{id:"canvas"})])])],-1),I=[v];function b(s,a,e,i,d,l){return m(),_("div",h,I)}const g=u(p,[["render",b]]);export{g as default}; diff --git a/_nuxt/B7NK_Nbm.js b/_nuxt/B7NK_Nbm.js deleted file mode 100644 index d05fb8bc..00000000 --- a/_nuxt/B7NK_Nbm.js +++ /dev/null @@ -1 +0,0 @@ -import{m,c as o,g as a,b as t,l as h,t as d,F as c,r as p,h as v,o as i}from"./CZZfhpmp.js";const b={mounted(){typeof navigator.requestMIDIAccess<"u"&&navigator.requestMIDIAccess().then(n=>{this.midi=n,this.midi.inputs.forEach(e=>{e.onmidimessage=u=>{this.events.push(u),this.events.length>15&&this.events.shift()}})},n=>{console.error(n)})},data(){return{tooltip:!1,midi:void 0,events:[]}},computed:{inputs(){if(typeof this.midi<"u")return Array.from(this.midi.inputs.values())},outputs(){if(typeof this.midi<"u")return Array.from(this.midi.outputs.values())}},filters:{midiCommand:n=>{switch(n){case 144:return"Note On";case 128:return"Note Off";default:return n}},midiNote:n=>`${["C","C# / Db","D","D# / Eb","E","F","F# / Bb","G","G# / Ab","A","A# / Bb","B"][n%12]} (${Math.floor(n/12)-2})`}},g={class:"h-2/3 bg-gradient-to-b from-green-100 to-green-50"},x={key:0,class:"p-4 text-center font-light tracking-wide"},_={key:1},y={class:"flex flex-wrap"},w={class:"absolute bottom-16 right-2"},k={class:"p-3 font-mono text-orange-900"},I={class:"mb-2 font-bold"},M={class:"mb-2"},N={key:0,class:"p-4 text-center italic"},D={key:1},C={class:"flex-1"},A={class:"flex-1"},z={class:"mb-2"},E={key:0,class:"p-4 text-center italic"},V={key:1},B={class:"flex-1"},F={class:"flex-1"},S={class:"absolute bottom-2 right-2"},O={class:"container mx-auto p-8"},P={class:"w-full table-auto border-2 border-green-800 bg-green-50 text-sm"},q={class:"divide-y divide-gray-100"},G={key:0},T={class:"p-2 text-left"},U={class:"p-2 text-left"},W={class:"p-2 text-left"},H={class:"p-2 text-left"},L={key:0,class:"p-2 text-left"},R={key:1,class:"p-2 text-left"},Y={class:"p-2 text-left"},j={class:"p-2 text-right"};function J(n,e,u,K,l,r){return i(),o("div",g,[typeof l.midi>"u"?(i(),o("div",x,e[1]||(e[1]=[a(" Unfortunately, the Web MIDI API is "),t("a",{class:"text-blue-500 underline",href:"https://developer.mozilla.org/en-US/docs/Web/API/MIDIMessageEvent#browser_compatibility"},"not supported",-1),a(" in all browsers... ")]))):(i(),o("div",_,[t("div",y,[t("div",w,[t("div",{class:h([{hidden:!l.tooltip,block:l.tooltip},"z-50 max-w-md break-words rounded-lg border-2 border-green-800 bg-yellow-200 text-sm font-normal leading-normal"])},[t("div",null,[e[5]||(e[5]=t("div",{class:"mb-0 rounded-t-lg border-b border-solid bg-green-600 p-3 font-semibold uppercase text-white opacity-75"}," MIDI Status ",-1)),t("div",k,[t("div",I,[e[2]||(e[2]=a(" Enabled: ")),t("span",null,d(typeof l.midi<"u"?"Yep!":"Nope"),1)]),t("div",M,[e[3]||(e[3]=t("div",{class:"font-bold"},"Inputs:",-1)),r.inputs.length===0?(i(),o("div",N," No input devices detected :( ")):(i(),o("div",D,[(i(!0),o(c,null,p(r.inputs,s=>(i(),o("div",{key:s.id,class:"flex"},[t("div",C,d(s.manufacturer),1),t("div",A,d(s.name),1)]))),128))]))]),t("div",z,[e[4]||(e[4]=t("div",{class:"font-bold"},"Outputs:",-1)),r.outputs.length===0?(i(),o("div",E," No output devices detected :( ")):(i(),o("div",V,[(i(!0),o(c,null,p(r.outputs,s=>(i(),o("div",{key:s.id,class:"flex"},[t("div",B,d(s.manufacturer),1),t("div",F,d(s.name),1)]))),128))]))])])])],2)]),t("div",S,[t("button",{ref:"btnRef",onClick:e[0]||(e[0]=s=>l.tooltip=!l.tooltip),class:"rounded-lg bg-green-800 px-2 py-1 text-white shadow hover:text-yellow-200 hover:shadow-lg",type:"button"},e[6]||(e[6]=[t("svg",{xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 20 20",class:"h-10 w-10"},[t("g",{fill:"none"},[t("path",{d:"M2.5 4a.5.5 0 0 0-.5.5v11a.5.5 0 0 0 .5.5h15a.5.5 0 0 0 .5-.5v-11a.5.5 0 0 0-.5-.5h-15zm.5 6h2v3.5a.5.5 0 0 0 1 0V10h2v3.5a.5.5 0 0 0 1 0V10h2v3.5a.5.5 0 0 0 1 0V10h2v3.5a.5.5 0 0 0 1 0V10h2v5H3v-5zm2.75-2.5a.75.75 0 1 1 0-1.5a.75.75 0 0 1 0 1.5zm6.25-1a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5zm-3 .251a.75.75 0 1 1-1.5 0a.75.75 0 0 1 1.5 0z",fill:"currentColor"})])],-1)]),512)])]),t("div",O,[e[9]||(e[9]=t("div",{class:"font-display text-4xl font-light tracking-wide"}," MIDI Events ",-1)),t("table",P,[e[8]||(e[8]=t("thead",{class:"bg-green-800 font-semibold uppercase text-white"},[t("tr",null,[t("th",{class:"p-2 text-left"},"Timestamp"),t("th",{class:"p-2 text-left"},"Command #"),t("th",{class:"p-2 text-left"},"Command"),t("th",{class:"p-2 text-left"},"Note #"),t("th",{class:"p-2 text-left"},"Note"),t("th",{class:"p-2 text-left"},"Velocity"),t("th",{class:"p-2 text-right"},"MIDI Source")])],-1)),t("tbody",q,[l.events.length===0?(i(),o("tr",G,e[7]||(e[7]=[t("td",{class:"p-4 text-center italic",colspan:"7"}," Press a key, or turn a knob! ",-1)]))):v("",!0),(i(!0),o(c,null,p(l.events,(s,f)=>(i(),o("tr",{key:f},[t("td",T,d(s.timeStamp.toFixed(2)),1),t("td",U,d(s.data[0]),1),t("td",W,d(s.data[0]|n.midiCommand),1),t("td",H,d(s.data[1]),1),s.data[0]===144||s.data[0]==128?(i(),o("td",L,d(s.data[1]|n.midiNote),1)):(i(),o("td",R,"-")),t("td",Y,d(s.data[2]),1),t("td",j,d(s.srcElement.name),1)]))),128))])])])]))])}const X=m(b,[["render",J]]);export{X as default}; diff --git a/_nuxt/eM-U89SY.js b/_nuxt/B8Io8PDA.js similarity index 65% rename from _nuxt/eM-U89SY.js rename to _nuxt/B8Io8PDA.js index 6458d111..a2ecd883 100644 --- a/_nuxt/eM-U89SY.js +++ b/_nuxt/B8Io8PDA.js @@ -1 +1 @@ -import{m as o,o as r,c as t,a8 as a}from"./CZZfhpmp.js";const s={};function c(e,n){return r(),t("thead",null,[a(e.$slots,"default")])}const d=o(s,[["render",c]]);export{d as default}; +import{m as o,o as r,c as t,a8 as a}from"./K1dcBiIN.js";const s={};function c(e,n){return r(),t("thead",null,[a(e.$slots,"default")])}const d=o(s,[["render",c]]);export{d as default}; diff --git a/_nuxt/BGlOumKY.js b/_nuxt/BGlOumKY.js new file mode 100644 index 00000000..d6bbf10f --- /dev/null +++ b/_nuxt/BGlOumKY.js @@ -0,0 +1 @@ +import{m as w,c as r,b as s,l as x,h as m,F as h,r as _,g as f,o as l,t as p}from"./K1dcBiIN.js";const v={data(){return{ix:0,a:[],b:[],timeline:[]}},computed:{step(){return this.timeline.length>0?this.timeline[this.ix]:{}},done(){return this.timeline.length-1===this.ix},started(){return this.timeline.length>0}},mounted(){this.generateRandomMatrices()},created(){typeof window>"u"||window.addEventListener("keydown",o=>{o.key===" "?this.incStep():o.key==="Escape"&&(this.ix=0)})},methods:{randomMatrix(o,n){const d=[];for(let b=0;bMath.round(Math.random()*10)));return d},generateRandomMatrices(){this.a=this.randomMatrix(3,4),this.b=this.randomMatrix(4,3),this.timeline=[],this.ix=0},matmul(o,n){this.timeline=[];const d=[];for(let c=0;c{n[e].forEach((i,t)=>{const g=[];o[e].forEach((a,u)=>{g.push(`${o[t][u]}*${n[u][e]}`),d[t][e]+=o[t][u]*n[u][e],b[e*o.length+t]=`${g.join(" + ")} = ${d[t][e]}`;const y=JSON.parse(JSON.stringify(d));this.timeline.push({row_a:t,col_a:u,row_b:u,col_b:e,row_c:t,col_c:e,cur_a:o[t][u],cur_b:n[u][e],cur_c:d[t][e],c:y,all_steps:b.slice()})})})})},incStep(){this.ix!==this.timeline.length-1&&(this.ix+=1)},decStep(){this.ix>0&&(this.ix-=1)}}},k={class:"m-4 space-y-4"},M=s("div",{class:"m-2 w-4/5"},[f(" Walk through the steps of matrix multiplication with randomly generated matrices. Press the "),s("em",null,"Spacebar"),f(" or click the "),s("em",{class:"bg-blue-200 text-blue-800"},"buttons"),f(" to iterate through the steps. ")],-1),S={class:"m-2 inline-flex space-x-2"},C=["disabled"],B=s("svg",{xmlns:"http://www.w3.org/2000/svg",class:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor"},[s("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M11 19l-7-7 7-7m8 14l-7-7 7-7"})],-1),E=[B],A=["disabled"],N=s("svg",{xmlns:"http://www.w3.org/2000/svg",class:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor"},[s("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M13 5l7 7-7 7M5 5l7 7-7 7"})],-1),R=[N],V={class:"flex flex-wrap"},D={class:"w-34 m-2 border border-gray-400 sm:w-min"},F=s("div",{class:"bg-gray-200 p-4 text-center font-bold"},"Matrix A",-1),J={class:"flex items-center justify-center p-4"},L={class:"text-center"},O={class:"w-34 m-2 border border-gray-400 sm:w-min"},z=s("div",{class:"bg-gray-200 p-4 text-center font-bold"},"Matrix B",-1),P={class:"flex items-center justify-center p-4"},T={class:"text-center"},W=s("div",{class:"bg-gray-200 p-4 text-center font-bold"},"Result",-1),q={class:"flex items-center justify-center p-4"},G={class:"text-center"},H={key:1,class:"m-2 w-72 border border-gray-400 bg-gray-100 p-2"},I=s("div",{class:"text-center font-bold"},"Steps",-1),K={class:"font-mono"},Q={key:0,class:"italic text-green-600"};function U(o,n,d,b,c,e){return l(),r("div",k,[M,s("div",S,[s("button",{class:x(["bg-blue-200 px-4 py-2 font-bold text-blue-800 hover:bg-blue-800 hover:text-blue-200",{"cursor-not-allowed opacity-25":!e.started}]),disabled:!e.started,onClick:n[0]||(n[0]=(...i)=>e.decStep&&e.decStep(...i))},E,10,C),e.done?m("",!0):(l(),r("button",{key:0,class:"bg-blue-200 px-4 py-2 font-bold text-blue-800 hover:bg-blue-800 hover:text-blue-200",onClick:n[1]||(n[1]=i=>e.matmul(c.a,c.b))}," Start ")),e.done?(l(),r("button",{key:1,class:"bg-orange-200 px-4 py-2 font-bold text-orange-800 hover:bg-blue-800 hover:text-blue-200",onClick:n[2]||(n[2]=(...i)=>e.generateRandomMatrices&&e.generateRandomMatrices(...i))}," Again! ")):m("",!0),s("button",{class:x(["bg-blue-200 px-4 py-2 font-bold text-blue-800 hover:bg-blue-800 hover:text-blue-200",{"cursor-not-allowed opacity-25":!e.started}]),disabled:!e.started,onClick:n[3]||(n[3]=(...i)=>e.incStep&&e.incStep(...i))},R,10,A)]),s("div",V,[s("div",D,[F,s("div",J,[s("table",L,[(l(!0),r(h,null,_(c.a,(i,t)=>(l(),r("tr",{key:t},[(l(!0),r(h,null,_(c.a[t],(g,a)=>(l(),r("td",{key:a,class:x([{"text-green-600":e.step&&t==e.step.row_a&&a==e.step.col_a,"bg-orange-100":e.step&&t==e.step.row_a},"p-2"])},p(c.a[t][a]),3))),128))]))),128))])])]),s("div",O,[z,s("div",P,[s("table",T,[(l(!0),r(h,null,_(c.b,(i,t)=>(l(),r("tr",{key:t},[(l(!0),r(h,null,_(c.b[t],(g,a)=>(l(),r("td",{key:a,class:x([{"text-green-600":e.step&&t==e.step.row_b&&a==e.step.col_b,"bg-orange-100":e.step&&a==e.step.col_b},"p-2"])},p(c.b[t][a]),3))),128))]))),128))])])]),e.started?(l(),r("div",{key:0,class:x(["m-2 w-72 border border-gray-400 sm:w-min",{"bg-green-200":e.done}])},[W,s("div",q,[s("table",G,[(l(!0),r(h,null,_(e.step.c,(i,t)=>(l(),r("tr",{key:t},[(l(!0),r(h,null,_(e.step.c[t],(g,a)=>(l(),r("td",{key:a,class:"p-2"},p(e.step.c[t][a]),1))),128))]))),128))])])],2)):m("",!0),e.started?(l(),r("div",H,[I,s("div",K,[(l(!0),r(h,null,_(e.step.all_steps,(i,t)=>(l(),r("div",{key:t},p(i),1))),128)),e.done?(l(),r("div",Q,"Done!")):m("",!0)])])):m("",!0)]),m("",!0)])}const Y=w(v,[["render",U]]);export{Y as default}; diff --git a/_nuxt/BMjn8cbr.js b/_nuxt/BMjn8cbr.js deleted file mode 100644 index 15550368..00000000 --- a/_nuxt/BMjn8cbr.js +++ /dev/null @@ -1 +0,0 @@ -import{c as t,b as r,o}from"./CZZfhpmp.js";const s={class:"flex h-[768px] justify-center border-2 border-gray-500"},c={__name:"metronome",setup(a){return(m,e)=>(o(),t("main",s,e[0]||(e[0]=[r("iframe",{src:"https://simple-tempo.com",width:"100%",height:"100%"},null,-1)])))}};export{c as default}; diff --git a/_nuxt/Bdjj16Wj.js b/_nuxt/BN984TM9.js similarity index 65% rename from _nuxt/Bdjj16Wj.js rename to _nuxt/BN984TM9.js index d491aac6..363181ae 100644 --- a/_nuxt/Bdjj16Wj.js +++ b/_nuxt/BN984TM9.js @@ -1 +1 @@ -import{m as o,o as r,c as t,a8 as a}from"./CZZfhpmp.js";const s={};function c(e,n){return r(),t("table",null,[a(e.$slots,"default")])}const f=o(s,[["render",c]]);export{f as default}; +import{m as o,o as r,c as t,a8 as a}from"./K1dcBiIN.js";const s={};function c(e,n){return r(),t("table",null,[a(e.$slots,"default")])}const f=o(s,[["render",c]]);export{f as default}; diff --git a/_nuxt/BNTwU45X.js b/_nuxt/BNTwU45X.js deleted file mode 100644 index 0f84d585..00000000 --- a/_nuxt/BNTwU45X.js +++ /dev/null @@ -1 +0,0 @@ -import{o as i,c as s,b as e,i as a,f as c,g as m,a as u,_ as d,k as v,t as g,F as w,r as y,e as x,h as k}from"./CZZfhpmp.js";function b(o,t){return i(),s("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 16 16",fill:"currentColor","aria-hidden":"true","data-slot":"icon"},[e("path",{"fill-rule":"evenodd",d:"M8.914 6.025a.75.75 0 0 1 1.06 0 3.5 3.5 0 0 1 0 4.95l-2 2a3.5 3.5 0 0 1-5.396-4.402.75.75 0 0 1 1.251.827 2 2 0 0 0 3.085 2.514l2-2a2 2 0 0 0 0-2.828.75.75 0 0 1 0-1.06Z","clip-rule":"evenodd"}),e("path",{"fill-rule":"evenodd",d:"M7.086 9.975a.75.75 0 0 1-1.06 0 3.5 3.5 0 0 1 0-4.95l2-2a3.5 3.5 0 0 1 5.396 4.402.75.75 0 0 1-1.251-.827 2 2 0 0 0-3.085-2.514l-2 2a2 2 0 0 0 0 2.828.75.75 0 0 1 0 1.06Z","clip-rule":"evenodd"})])}const M={class:"flex justify-end"},I={__name:"MoreLink",props:{to:{type:String,required:!0}},setup(o){const t=o;return(l,r)=>{const p=d;return i(),s("div",M,[a(p,{to:t.to,class:"flex items-center text-sm font-bold text-white hover:text-orange-500"},{default:c(()=>[r[0]||(r[0]=m(" More ")),a(u(b),{class:"ml-1 h-5 w-5","aria-hidden":"true"})]),_:1},8,["to"])])}}},j={class:"bg-gradient-to-b from-transparent to-background text-white"},D={class:"container mx-auto space-y-4 py-8 text-white"},L={class:"mb-4 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3"},P=["src"],V={class:"absolute top-0 h-full flex items-center justify-center bg-gray-500/50"},B={class:"m-2 bg-black/70 p-2"},C={class:"text-xl font-bold text-orange-500"},N=["innerHTML"],S={key:0},T="Experiments",E={__name:"Playground",props:{showImages:{type:Boolean,default:!1},limit:{type:Number,default:null},linkToPlayground:{type:Boolean,default:!1}},setup(o){const t=o,l=[{title:"Conway",description:"Conway's game of life written in vanilla Javascript",link:"/playground/conway",img:"/images/previews/conway.png"},{title:"wm.spoon",description:"Window manager for Hammer Spoon written in Lua",link:"https://github.com/cmpadden/wm.spoon",img:"/images/previews/wm.spoon.png"},{title:"Metronome",description:"A simple metronome for tracking tempo in the browser",link:"/playground/metronome",img:"/images/previews/metronome.png"},{title:"Conjugations",description:"Search and explore the conjugations of 1000 French verbs",link:"/playground/french",img:"/images/previews/french-conjugations.png"},{title:"Mountains",description:"Visualize a gradient of colored waves generated with Perlin noise",link:"/playground/palettes/mountains",img:"/images/previews/noise.png"},{title:"Spectrogram",description:"Visualize the audio from your microphone as a waveform, frequency bars, and a spectrogram",link:"/playground/audio",img:"/images/previews/microphone.png"},{title:"Waves",description:"Demonstration of using p5.js within Vue.js to visualize trigonometric functions",link:"/playground/waves",img:"/images/previews/waves.png"},{title:"MIDI Chords",description:"Identify the chords being played by your attached MIDI device",link:"/playground/chords",img:"/images/previews/chord-identifier.png"},{title:"MIDI Events",description:"View the MIDI events triggered by a MIDI-controller through the Web MIDI API",link:"/playground/midi",img:"/images/previews/midi-events.png"},{title:"Matrix Multiplication",description:"Step through the process of matrix multiplication",link:"/playground/matrix",img:"/images/previews/matrix-multiplication.png"},{title:"Sequence Plotter",description:"Plot the fist 10,000 digits of Pi, or any sequence of digits, in 2-dimensional space",link:"/playground/plotter",img:"/images/previews/plotter.png"}],r=v(()=>t.limit===null||t.limit<=0?l:l.slice(0,t.limit));return(p,q)=>{const h=d,f=d,_=I;return i(),s("section",j,[e("div",D,[a(h,{to:"/playground",class:"font-mono text-3xl font-semibold lowercase underline decoration-orange-500 underline-offset-4 hover:text-orange-500"},{default:c(()=>[m(g(T))]),_:1}),e("div",L,[(i(!0),s(w,null,y(u(r),n=>(i(),x(f,{class:"relative drop-shadow-lg hover:ring-1 hover:ring-white",key:n.title,to:n.link},{default:c(()=>[e("img",{class:"grayscale-1 h-full w-full object-cover",src:n.img||"images/placeholder.png"},null,8,P),e("div",V,[e("div",B,[e("h3",C,g(n.title),1),e("div",{class:"line-clamp-2 text-sm text-gray-300",innerHTML:n.description},null,8,N)])])]),_:2},1032,["to"]))),128))]),o.linkToPlayground?(i(),s("div",S,[a(_,{to:"/playground"})])):k("",!0)])])}}};export{I as _,E as a}; diff --git a/_nuxt/Dtl8qhH9.js b/_nuxt/BPDZZsV6.js similarity index 64% rename from _nuxt/Dtl8qhH9.js rename to _nuxt/BPDZZsV6.js index 00a36cf5..5bbb9aa0 100644 --- a/_nuxt/Dtl8qhH9.js +++ b/_nuxt/BPDZZsV6.js @@ -1 +1 @@ -import{m as o,o as r,c as s,a8 as t}from"./CZZfhpmp.js";const c={};function n(e,a){return r(),s("ul",null,[t(e.$slots,"default")])}const f=o(c,[["render",n]]);export{f as default}; +import{m as o,o as r,c as s,a8 as t}from"./K1dcBiIN.js";const c={};function n(e,a){return r(),s("ul",null,[t(e.$slots,"default")])}const f=o(c,[["render",n]]);export{f as default}; diff --git a/_nuxt/BPNqVqzl.js b/_nuxt/BPNqVqzl.js new file mode 100644 index 00000000..10dc93c5 --- /dev/null +++ b/_nuxt/BPNqVqzl.js @@ -0,0 +1 @@ +import{d as f,o,c as s,b as e,h as u,g as n,i as a,f as m,F as x,r as b,t as _,_ as v,w,a as y}from"./K1dcBiIN.js";import{_ as k,a as $}from"./Bildd8lj.js";import{q as C}from"./Ce34VGij.js";import"./DvDH6DOc.js";import"./NnUIAPGH.js";const D={class:"container mx-auto pb-8"},S={class:"flex flex-wrap"},A={class:"w-full"},B={class:"lg:text-normal space-y-4 text-justify font-medium tracking-wide text-white sm:text-base"},I=e("div",null,[n(" I help educate data engineers while building the future of data orchestration at "),e("a",{class:"border-b-2 border-orange-500",target:"_blank",rel:"noopener noreferrer",href:"https://dagster.io/"},"Dagster"),n(". ")],-1),N=e("div",null,[n(" Previously, I worked at "),e("a",{class:"border-b-2 border-orange-500",target:"_blank",rel:"noopener noreferrer",href:"https://www.gemini.com/"},"Gemini"),n(" building the data platform that provided company-wide insights into the exchange and business. At Georgetown University's "),e("a",{class:"border-b-2 border-orange-500",target:"_blank",rel:"noopener noreferrer",href:"https://mccourt.georgetown.edu/research/the-massive-data-institute/"},"Massive Data Institute"),n(" building data warehousing, processing solutions, and portals to aid social scientists and researchers to leverage large-scale organic data. And previously I provided consulting for financial institutions and government agencies in the D.C. area around data practices, and identity and access management. ")],-1),P=f({__name:"AboutMe",setup(i){return(t,c)=>(o(),s("section",D,[e("div",S,[e("div",A,[e("div",B,[u("",!0),I,N])])])]))}}),L={class:"bg-gradient-to-b from-background to-transparent"},M={class:"container mx-auto space-y-4"},V={class:"mb-4 grid grid-cols-1 gap-4 md:grid-cols-2"},q={class:"h-full space-y-4 bg-black/70 p-4 text-white drop-shadow-lg hover:ring-1 hover:ring-white"},F={class:"flex-1 text-lg font-bold md:text-xl"},G={key:0,class:"text-sm font-light text-gray-400"},T={class:"line-clamp-3 text-sm text-gray-300"},U={__name:"BlogPosts",props:{articles:[],show_dates:!1},setup(i){return(t,c)=>{const d=v,g=k;return o(),s("section",L,[e("div",M,[a(d,{to:"/articles",class:"font-mono text-3xl font-semibold text-white underline decoration-orange-500 underline-offset-4 hover:text-orange-500"},{default:m(()=>[n(" blog posts ")]),_:1}),e("div",V,[(o(!0),s(x,null,b(i.articles,(r,l)=>(o(),s("div",{key:l},[a(d,{to:r._path,external:""},{default:m(()=>[e("div",q,[e("div",null,[e("div",F,_(r.title),1),i.show_dates?(o(),s("div",G,_(new Date(r.date).toLocaleDateString("en-US",{month:"long",day:"numeric",year:"numeric"})),1)):u("",!0)]),e("div",T,_(r.description),1)])]),_:2},1032,["to"])]))),128))]),e("div",null,[a(g,{to:"/articles"})])])])}}},j={class:"bg-emerald-950 bg-[url('/images/noise.svg')]"},O={__name:"index",async setup(i){let t,c;const d=([t,c]=w(()=>C().only(["_id","_path","title","description","date","img","author","tags"]).sort({date:-1}).limit(4).find()),t=await t,c(),t);return(g,r)=>{const l=P,h=U,p=$;return o(),s("div",null,[a(l),e("div",j,[u("",!0),a(h,{articles:y(d),show_dates:!0},null,8,["articles"]),a(p,{limit:9,showImages:"",linkToPlayground:""})])])}}};export{O as default}; diff --git a/_nuxt/Bg6Wkwu9.js b/_nuxt/BRI1TGcF.js similarity index 58% rename from _nuxt/Bg6Wkwu9.js rename to _nuxt/BRI1TGcF.js index d4cbca30..9149fdbe 100644 --- a/_nuxt/Bg6Wkwu9.js +++ b/_nuxt/BRI1TGcF.js @@ -1 +1 @@ -import{d as n,L as e}from"./CZZfhpmp.js";const t=n({name:"DocumentDrivenNotFound",render(){return e("div","Document not found")}});export{t as default}; +import{d as n,L as e}from"./K1dcBiIN.js";const t=n({name:"DocumentDrivenNotFound",render(){return e("div","Document not found")}});export{t as default}; diff --git a/_nuxt/BSSPlG-l.js b/_nuxt/BSSPlG-l.js new file mode 100644 index 00000000..70f0bd6f --- /dev/null +++ b/_nuxt/BSSPlG-l.js @@ -0,0 +1 @@ +import{d as i,I as c,k as p,o as s,c as n,a as u,a8 as t}from"./K1dcBiIN.js";const f=["id"],l=["href"],k=i({__name:"ProseH3",props:{id:{}},setup(a){const r=a,{headings:o}=c().public.mdc,d=p(()=>{var e;return r.id&&((e=o==null?void 0:o.anchorLinks)==null?void 0:e.h3)});return(e,m)=>(s(),n("h3",{id:e.id},[e.id&&u(d)?(s(),n("a",{key:0,href:`#${e.id}`},[t(e.$slots,"default")],8,l)):t(e.$slots,"default",{key:1})],8,f))}});export{k as default}; diff --git a/_nuxt/BT8WlydD.js b/_nuxt/BT8WlydD.js new file mode 100644 index 00000000..a459a607 --- /dev/null +++ b/_nuxt/BT8WlydD.js @@ -0,0 +1 @@ +import{m as x,c as u,o as v,b as c}from"./K1dcBiIN.js";const _={data(){return{}},mounted(){document.getElementById("canvas").textContent="";const o=["#FFBA08","#FAA307","#F48C06","#E85D04","#DC2F02","#D00000","#9D0208","#6A040F","#370617","#03071E"],i=e=>{const r=document.getElementById("canvas"),a=r.clientWidth,n=r.clientHeight,f=[{color:o[1],min:0,max:.2,yoff:2},{color:o[2],min:.2,max:.4,yoff:2},{color:o[3],min:.4,max:.6,yoff:2},{color:o[4],min:.6,max:.8,yoff:2},{color:o[5],min:.8,max:1,yoff:2}],l=t=>{e.fill(t.color),e.beginShape();let d=1;for(let m=0;m<=a;m+=10){const h=e.map(e.noise(d,t.yoff),0,1,t.min*n,t.max*n);e.curveVertex(m,h),d+=e.random(.5)}t.yoff+=e.random(-.5,.5),e.curveVertex(a,n),e.curveVertex(0,n),e.endShape(e.CLOSE)},s=()=>{e.clear(),e.background(o[0]),f.forEach(t=>l(t))};e.setup=()=>{e.createCanvas(a,n),e.frameRate(5),e.smooth(),e.stroke(255),e.strokeWeight(3),s(),e.noLoop()},e.mousePressed=()=>{s()}};new this.$p5(i,"canvas")}},y={class:"select-none bg-gradient-to-b from-green-800 to-gray-800"},p=c("div",{class:"m-6 grid h-2/3 place-items-center"},[c("div",{class:"font-mono text-white"},[c("div",{id:"canvas",class:"mb-2 h-96 border-2 border-white"}),c("div",{class:"my-2 w-48 text-center md:w-full"}," Click or tap anywhere to redraw the waves! ")])],-1),g=[p];function w(o,i,e,r,a,n){return v(),u("div",y,g)}const b=x(_,[["render",w]]);export{b as default}; diff --git a/_nuxt/BUQkeXPm.js b/_nuxt/BUQkeXPm.js deleted file mode 100644 index 5defa9d4..00000000 --- a/_nuxt/BUQkeXPm.js +++ /dev/null @@ -1 +0,0 @@ -import{d as p,I as f,k as i,o as t,c as s,a as u,a8 as n}from"./CZZfhpmp.js";const l=["id"],d=["href"],_=p({__name:"ProseH2",props:{id:{}},setup(r){const a=r,{headings:o}=f().public.mdc,c=i(()=>{var e;return a.id&&(typeof(o==null?void 0:o.anchorLinks)=="boolean"&&(o==null?void 0:o.anchorLinks)===!0||typeof(o==null?void 0:o.anchorLinks)=="object"&&((e=o==null?void 0:o.anchorLinks)==null?void 0:e.h2))});return(e,k)=>(t(),s("h2",{id:e.id},[e.id&&u(c)?(t(),s("a",{key:0,href:`#${e.id}`},[n(e.$slots,"default")],8,d)):n(e.$slots,"default",{key:1})],8,l))}});export{_ as default}; diff --git a/_nuxt/BbJBDj-J.js b/_nuxt/BbJBDj-J.js deleted file mode 100644 index f1f11ca8..00000000 --- a/_nuxt/BbJBDj-J.js +++ /dev/null @@ -1 +0,0 @@ -import{m as _,c as l,b as s,g as y,l as p,h as g,F as b,r as m,o as n,t as f}from"./CZZfhpmp.js";const v={data(){return{ix:0,a:[],b:[],timeline:[]}},computed:{step(){return this.timeline.length>0?this.timeline[this.ix]:{}},done(){return this.timeline.length-1===this.ix},started(){return this.timeline.length>0}},mounted(){this.generateRandomMatrices()},created(){typeof window>"u"||window.addEventListener("keydown",o=>{o.key===" "?this.incStep():o.key==="Escape"&&(this.ix=0)})},methods:{randomMatrix(o,t){const c=[];for(let h=0;hMath.round(Math.random()*10)));return c},generateRandomMatrices(){this.a=this.randomMatrix(3,4),this.b=this.randomMatrix(4,3),this.timeline=[],this.ix=0},matmul(o,t){this.timeline=[];const c=[];for(let i=0;i{t[e].forEach((a,r)=>{const x=[];o[e].forEach((d,u)=>{x.push(`${o[r][u]}*${t[u][e]}`),c[r][e]+=o[r][u]*t[u][e],h[e*o.length+r]=`${x.join(" + ")} = ${c[r][e]}`;const w=JSON.parse(JSON.stringify(c));this.timeline.push({row_a:r,col_a:u,row_b:u,col_b:e,row_c:r,col_c:e,cur_a:o[r][u],cur_b:t[u][e],cur_c:c[r][e],c:w,all_steps:h.slice()})})})})},incStep(){this.ix!==this.timeline.length-1&&(this.ix+=1)},decStep(){this.ix>0&&(this.ix-=1)}}},k={class:"m-4 space-y-4"},M={class:"m-2 inline-flex space-x-2"},S=["disabled"],C=["disabled"],B={class:"flex flex-wrap"},E={class:"w-34 m-2 border border-gray-400 sm:w-min"},A={class:"flex items-center justify-center p-4"},N={class:"text-center"},R={class:"w-34 m-2 border border-gray-400 sm:w-min"},V={class:"flex items-center justify-center p-4"},D={class:"text-center"},F={class:"flex items-center justify-center p-4"},J={class:"text-center"},L={key:1,class:"m-2 w-72 border border-gray-400 bg-gray-100 p-2"},O={class:"font-mono"},z={key:0,class:"italic text-green-600"};function P(o,t,c,h,i,e){return n(),l("div",k,[t[10]||(t[10]=s("div",{class:"m-2 w-4/5"},[y(" Walk through the steps of matrix multiplication with randomly generated matrices. Press the "),s("em",null,"Spacebar"),y(" or click the "),s("em",{class:"bg-blue-200 text-blue-800"},"buttons"),y(" to iterate through the steps. ")],-1)),s("div",M,[s("button",{class:p(["bg-blue-200 px-4 py-2 font-bold text-blue-800 hover:bg-blue-800 hover:text-blue-200",{"cursor-not-allowed opacity-25":!e.started}]),disabled:!e.started,onClick:t[0]||(t[0]=(...a)=>e.decStep&&e.decStep(...a))},t[4]||(t[4]=[s("svg",{xmlns:"http://www.w3.org/2000/svg",class:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor"},[s("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M11 19l-7-7 7-7m8 14l-7-7 7-7"})],-1)]),10,S),e.done?g("",!0):(n(),l("button",{key:0,class:"bg-blue-200 px-4 py-2 font-bold text-blue-800 hover:bg-blue-800 hover:text-blue-200",onClick:t[1]||(t[1]=a=>e.matmul(i.a,i.b))}," Start ")),e.done?(n(),l("button",{key:1,class:"bg-orange-200 px-4 py-2 font-bold text-orange-800 hover:bg-blue-800 hover:text-blue-200",onClick:t[2]||(t[2]=(...a)=>e.generateRandomMatrices&&e.generateRandomMatrices(...a))}," Again! ")):g("",!0),s("button",{class:p(["bg-blue-200 px-4 py-2 font-bold text-blue-800 hover:bg-blue-800 hover:text-blue-200",{"cursor-not-allowed opacity-25":!e.started}]),disabled:!e.started,onClick:t[3]||(t[3]=(...a)=>e.incStep&&e.incStep(...a))},t[5]||(t[5]=[s("svg",{xmlns:"http://www.w3.org/2000/svg",class:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor"},[s("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M13 5l7 7-7 7M5 5l7 7-7 7"})],-1)]),10,C)]),s("div",B,[s("div",E,[t[6]||(t[6]=s("div",{class:"bg-gray-200 p-4 text-center font-bold"},"Matrix A",-1)),s("div",A,[s("table",N,[(n(!0),l(b,null,m(i.a,(a,r)=>(n(),l("tr",{key:r},[(n(!0),l(b,null,m(i.a[r],(x,d)=>(n(),l("td",{key:d,class:p([{"text-green-600":e.step&&r==e.step.row_a&&d==e.step.col_a,"bg-orange-100":e.step&&r==e.step.row_a},"p-2"])},f(i.a[r][d]),3))),128))]))),128))])])]),s("div",R,[t[7]||(t[7]=s("div",{class:"bg-gray-200 p-4 text-center font-bold"},"Matrix B",-1)),s("div",V,[s("table",D,[(n(!0),l(b,null,m(i.b,(a,r)=>(n(),l("tr",{key:r},[(n(!0),l(b,null,m(i.b[r],(x,d)=>(n(),l("td",{key:d,class:p([{"text-green-600":e.step&&r==e.step.row_b&&d==e.step.col_b,"bg-orange-100":e.step&&d==e.step.col_b},"p-2"])},f(i.b[r][d]),3))),128))]))),128))])])]),e.started?(n(),l("div",{key:0,class:p(["m-2 w-72 border border-gray-400 sm:w-min",{"bg-green-200":e.done}])},[t[8]||(t[8]=s("div",{class:"bg-gray-200 p-4 text-center font-bold"},"Result",-1)),s("div",F,[s("table",J,[(n(!0),l(b,null,m(e.step.c,(a,r)=>(n(),l("tr",{key:r},[(n(!0),l(b,null,m(e.step.c[r],(x,d)=>(n(),l("td",{key:d,class:"p-2"},f(e.step.c[r][d]),1))),128))]))),128))])])],2)):g("",!0),e.started?(n(),l("div",L,[t[9]||(t[9]=s("div",{class:"text-center font-bold"},"Steps",-1)),s("div",O,[(n(!0),l(b,null,m(e.step.all_steps,(a,r)=>(n(),l("div",{key:r},f(a),1))),128)),e.done?(n(),l("div",z,"Done!")):g("",!0)])])):g("",!0)]),g("",!0)])}const W=_(v,[["render",P]]);export{W as default}; diff --git a/_nuxt/BbWmv1K-.js b/_nuxt/BbWmv1K-.js deleted file mode 100644 index 1a59c1ba..00000000 --- a/_nuxt/BbWmv1K-.js +++ /dev/null @@ -1 +0,0 @@ -import{m as p,o as b,c,b as i,C as r,D as m,i as u}from"./CZZfhpmp.js";const w={props:{id:{type:String,default:"canvas"},canvasHeight:{type:Number,default:250},type:{type:String,default:"sin"},diameter:{type:Number,default:15},amplitude:{type:Number,default:75},lambda:{type:Number,default:266}},mounted(){const o=e=>{const a=e.windowWidth>=450?this.canvasHeight:200,s=e.windowWidth>=450?800:300;let t=0,d=a/2,n=0;const l=100,v=125;e.setup=()=>{e.createCanvas(s,a),t=-this.diameter},e.draw=()=>{this.type==="sin"?d=this.amplitude*e.sin(t*(e.TWO_PI/this.lambda))+a/2:this.type==="cos"?d=this.amplitude*e.cos(t*(e.TWO_PI/this.lambda))+a/2:this.type==="tan"?d=this.amplitude*e.tan(t*(e.TWO_PI/this.lambda))+a/2:d=a/2,n=Math.round(e.map(d,-this.amplitude+a/2,this.amplitude+a/2,0,255)),t=t>=s+this.diameter?-this.diameter:t+1,e.noStroke(),e.fill(e.color(n,l,v)),e.ellipse(t,d,this.diameter,this.diameter)},e.mousePressed=()=>{e.clear()}};new this.$p5(o,this.id)},data(){return{}}},f=["id"];function h(o,e,a,s,t,d){return b(),c("div",{id:a.id},null,8,f)}const y=p(w,[["render",h]]),_={data(){return{wave:{amplitude:75,lambda:266,diameter:15}}}},x={class:"bg-gradient-to-b from-green-800 to-gray-800"},g={class:"grid h-screen place-items-center"},I={class:"font-mono text-white"},k={class:"my-2 items-end md:flex"},W={class:"hidden md:block"},N={class:"mb-2 border-2 border-white"},T={class:"mb-2 border-2 border-white"},H={class:"border-2 border-white"};function P(o,e,a,s,t,d){const n=y;return b(),c("div",x,[i("div",g,[i("div",I,[i("div",k,[e[6]||(e[6]=i("div",{class:"flex-none md:flex-1"},"y(x) = A sin((2π / λ) x)",-1)),i("div",W,[e[3]||(e[3]=i("label",{for:"aInput",class:"form-label inline-block"},"A",-1)),r(i("input",{id:"aInput","onUpdate:modelValue":e[0]||(e[0]=l=>t.wave.amplitude=l),type:"number",class:"w-16 border-2 border-white bg-transparent p-2 focus:outline-none"},null,512),[[m,t.wave.amplitude,void 0,{number:!0}]]),e[4]||(e[4]=i("label",{for:"lInput",class:"form-label inline-block"},"λ",-1)),r(i("input",{id:"lInput","onUpdate:modelValue":e[1]||(e[1]=l=>t.wave.lambda=l),type:"number",class:"w-16 border-2 border-white bg-transparent p-2 focus:outline-none"},null,512),[[m,t.wave.lambda,void 0,{number:!0}]]),e[5]||(e[5]=i("label",{for:"dInput",class:"form-label inline-block"},"◒",-1)),r(i("input",{id:"dInput","onUpdate:modelValue":e[2]||(e[2]=l=>t.wave.diameter=l),type:"number",class:"w-16 border-2 border-white bg-transparent p-2 focus:outline-none"},null,512),[[m,t.wave.diameter,void 0,{number:!0}]])])]),i("div",N,[u(n,{id:"canvas1",type:"sin",diameter:t.wave.diameter,amplitude:t.wave.amplitude,lambda:t.wave.lambda},null,8,["diameter","amplitude","lambda"])]),e[7]||(e[7]=i("div",null,"y(x) = A cos((2π / λ) x)",-1)),i("div",T,[u(n,{id:"canvas2",type:"cos",diameter:t.wave.diameter,amplitude:t.wave.amplitude,lambda:t.wave.lambda},null,8,["diameter","amplitude","lambda"])]),e[8]||(e[8]=i("div",null,"y(x) = A tan((2π / λ) x)",-1)),i("div",H,[u(n,{id:"canvas3",type:"tan",diameter:t.wave.diameter,amplitude:t.wave.amplitude,lambda:t.wave.lambda},null,8,["diameter","amplitude","lambda"])]),e[9]||(e[9]=i("div",{class:"my-2 w-48 md:w-full"}," Click or tap anywhere to clear the canvas! ",-1))])])])}const A=p(_,[["render",P]]);export{A as default}; diff --git a/_nuxt/Bf0jujID.js b/_nuxt/Bf0jujID.js new file mode 100644 index 00000000..536597e9 --- /dev/null +++ b/_nuxt/Bf0jujID.js @@ -0,0 +1 @@ +import{m as c,o as p,c as b,b as i,C as r,D as m,i as u}from"./K1dcBiIN.js";const _={props:{id:{type:String,default:"canvas"},canvasHeight:{type:Number,default:250},type:{type:String,default:"sin"},diameter:{type:Number,default:15},amplitude:{type:Number,default:75},lambda:{type:Number,default:266}},mounted(){const o=e=>{const a=e.windowWidth>=450?this.canvasHeight:200,l=e.windowWidth>=450?800:300;let t=0,d=a/2,s=0;const n=100,h=125;e.setup=()=>{e.createCanvas(l,a),t=-this.diameter},e.draw=()=>{this.type==="sin"?d=this.amplitude*e.sin(t*(e.TWO_PI/this.lambda))+a/2:this.type==="cos"?d=this.amplitude*e.cos(t*(e.TWO_PI/this.lambda))+a/2:this.type==="tan"?d=this.amplitude*e.tan(t*(e.TWO_PI/this.lambda))+a/2:d=a/2,s=Math.round(e.map(d,-this.amplitude+a/2,this.amplitude+a/2,0,255)),t=t>=l+this.diameter?-this.diameter:t+1,e.noStroke(),e.fill(e.color(s,n,h)),e.ellipse(t,d,this.diameter,this.diameter)},e.mousePressed=()=>{e.clear()}};new this.$p5(o,this.id)},data(){return{}}},v=["id"];function w(o,e,a,l,t,d){return p(),b("div",{id:a.id},null,8,v)}const f=c(_,[["render",w]]),y={data(){return{wave:{amplitude:75,lambda:266,diameter:15}}}},x={class:"bg-gradient-to-b from-green-800 to-gray-800"},g={class:"grid h-screen place-items-center"},I={class:"font-mono text-white"},k={class:"my-2 items-end md:flex"},W=i("div",{class:"flex-none md:flex-1"},"y(x) = A sin((2π / λ) x)",-1),N={class:"hidden md:block"},T=i("label",{for:"aInput",class:"form-label inline-block"},"A",-1),H=i("label",{for:"lInput",class:"form-label inline-block"},"λ",-1),P=i("label",{for:"dInput",class:"form-label inline-block"},"◒",-1),V={class:"mb-2 border-2 border-white"},A=i("div",null,"y(x) = A cos((2π / λ) x)",-1),B={class:"mb-2 border-2 border-white"},C=i("div",null,"y(x) = A tan((2π / λ) x)",-1),D={class:"border-2 border-white"},O=i("div",{class:"my-2 w-48 md:w-full"}," Click or tap anywhere to clear the canvas! ",-1);function S(o,e,a,l,t,d){const s=f;return p(),b("div",x,[i("div",g,[i("div",I,[i("div",k,[W,i("div",N,[T,r(i("input",{id:"aInput","onUpdate:modelValue":e[0]||(e[0]=n=>t.wave.amplitude=n),type:"number",class:"w-16 border-2 border-white bg-transparent p-2 focus:outline-none"},null,512),[[m,t.wave.amplitude,void 0,{number:!0}]]),H,r(i("input",{id:"lInput","onUpdate:modelValue":e[1]||(e[1]=n=>t.wave.lambda=n),type:"number",class:"w-16 border-2 border-white bg-transparent p-2 focus:outline-none"},null,512),[[m,t.wave.lambda,void 0,{number:!0}]]),P,r(i("input",{id:"dInput","onUpdate:modelValue":e[2]||(e[2]=n=>t.wave.diameter=n),type:"number",class:"w-16 border-2 border-white bg-transparent p-2 focus:outline-none"},null,512),[[m,t.wave.diameter,void 0,{number:!0}]])])]),i("div",V,[u(s,{id:"canvas1",type:"sin",diameter:t.wave.diameter,amplitude:t.wave.amplitude,lambda:t.wave.lambda},null,8,["diameter","amplitude","lambda"])]),A,i("div",B,[u(s,{id:"canvas2",type:"cos",diameter:t.wave.diameter,amplitude:t.wave.amplitude,lambda:t.wave.lambda},null,8,["diameter","amplitude","lambda"])]),C,i("div",D,[u(s,{id:"canvas3",type:"tan",diameter:t.wave.diameter,amplitude:t.wave.amplitude,lambda:t.wave.lambda},null,8,["diameter","amplitude","lambda"])]),O])])])}const E=c(y,[["render",S]]);export{E as default}; diff --git a/_nuxt/Bildd8lj.js b/_nuxt/Bildd8lj.js new file mode 100644 index 00000000..a326a867 --- /dev/null +++ b/_nuxt/Bildd8lj.js @@ -0,0 +1 @@ +import{o as i,c as s,b as e,i as r,f as l,g as m,a as u,_ as c,k as v,t as g,F as w,r as y,e as x,h as k}from"./K1dcBiIN.js";function b(o,t){return i(),s("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 16 16",fill:"currentColor","aria-hidden":"true","data-slot":"icon"},[e("path",{"fill-rule":"evenodd",d:"M8.914 6.025a.75.75 0 0 1 1.06 0 3.5 3.5 0 0 1 0 4.95l-2 2a3.5 3.5 0 0 1-5.396-4.402.75.75 0 0 1 1.251.827 2 2 0 0 0 3.085 2.514l2-2a2 2 0 0 0 0-2.828.75.75 0 0 1 0-1.06Z","clip-rule":"evenodd"}),e("path",{"fill-rule":"evenodd",d:"M7.086 9.975a.75.75 0 0 1-1.06 0 3.5 3.5 0 0 1 0-4.95l2-2a3.5 3.5 0 0 1 5.396 4.402.75.75 0 0 1-1.251-.827 2 2 0 0 0-3.085-2.514l-2 2a2 2 0 0 0 0 2.828.75.75 0 0 1 0 1.06Z","clip-rule":"evenodd"})])}const M={class:"flex justify-end"},I={__name:"MoreLink",props:{to:{type:String,required:!0}},setup(o){const t=o;return(a,d)=>{const p=c;return i(),s("div",M,[r(p,{to:t.to,class:"flex items-center text-sm font-bold text-white hover:text-orange-500"},{default:l(()=>[m(" More "),r(u(b),{class:"ml-1 h-5 w-5","aria-hidden":"true"})]),_:1},8,["to"])])}}},j={class:"bg-gradient-to-b from-transparent to-background text-white"},D={class:"container mx-auto space-y-4 py-8 text-white"},L={class:"mb-4 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3"},P=["src"],V={class:"absolute top-0 flex h-full items-center justify-center bg-gray-500/50"},B={class:"m-2 bg-black/70 p-2"},C={class:"text-xl font-bold text-orange-500"},N=["innerHTML"],S={key:0},T="Experiments",E={__name:"Playground",props:{showImages:{type:Boolean,default:!1},limit:{type:Number,default:null},linkToPlayground:{type:Boolean,default:!1}},setup(o){const t=o,a=[{title:"Conway",description:"Conway's game of life written in vanilla Javascript",link:"/playground/conway",img:"/images/previews/conway.png"},{title:"wm.spoon",description:"Window manager for Hammer Spoon written in Lua",link:"https://github.com/cmpadden/wm.spoon",img:"/images/previews/wm.spoon.png"},{title:"Metronome",description:"A simple metronome for tracking tempo in the browser",link:"/playground/metronome",img:"/images/previews/metronome.png"},{title:"Conjugations",description:"Search and explore the conjugations of 1000 French verbs",link:"/playground/french",img:"/images/previews/french-conjugations.png"},{title:"Mountains",description:"Visualize a gradient of colored waves generated with Perlin noise",link:"/playground/palettes/mountains",img:"/images/previews/noise.png"},{title:"Spectrogram",description:"Visualize the audio from your microphone as a waveform, frequency bars, and a spectrogram",link:"/playground/audio",img:"/images/previews/microphone.png"},{title:"Waves",description:"Demonstration of using p5.js within Vue.js to visualize trigonometric functions",link:"/playground/waves",img:"/images/previews/waves.png"},{title:"MIDI Chords",description:"Identify the chords being played by your attached MIDI device",link:"/playground/chords",img:"/images/previews/chord-identifier.png"},{title:"MIDI Events",description:"View the MIDI events triggered by a MIDI-controller through the Web MIDI API",link:"/playground/midi",img:"/images/previews/midi-events.png"},{title:"Matrix Multiplication",description:"Step through the process of matrix multiplication",link:"/playground/matrix",img:"/images/previews/matrix-multiplication.png"},{title:"Sequence Plotter",description:"Plot the fist 10,000 digits of Pi, or any sequence of digits, in 2-dimensional space",link:"/playground/plotter",img:"/images/previews/plotter.png"}],d=v(()=>t.limit===null||t.limit<=0?a:a.slice(0,t.limit));return(p,q)=>{const h=c,f=c,_=I;return i(),s("section",j,[e("div",D,[r(h,{to:"/playground",class:"font-mono text-3xl font-semibold lowercase underline decoration-orange-500 underline-offset-4 hover:text-orange-500"},{default:l(()=>[m(g(T))]),_:1}),e("div",L,[(i(!0),s(w,null,y(u(d),n=>(i(),x(f,{class:"relative drop-shadow-lg hover:ring-1 hover:ring-white",key:n.title,to:n.link},{default:l(()=>[e("img",{class:"grayscale-1 h-full w-full object-cover",src:n.img||"images/placeholder.png"},null,8,P),e("div",V,[e("div",B,[e("h3",C,g(n.title),1),e("div",{class:"line-clamp-2 text-sm text-gray-300",innerHTML:n.description},null,8,N)])])]),_:2},1032,["to"]))),128))]),o.linkToPlayground?(i(),s("div",S,[r(_,{to:"/playground"})])):k("",!0)])])}}};export{I as _,E as a}; diff --git a/_nuxt/BTZnUlcA.js b/_nuxt/BnxxK6MW.js similarity index 65% rename from _nuxt/BTZnUlcA.js rename to _nuxt/BnxxK6MW.js index 85280b8e..9e9b90a8 100644 --- a/_nuxt/BTZnUlcA.js +++ b/_nuxt/BnxxK6MW.js @@ -1 +1 @@ -import{m as o,o as r,c as t,a8 as n}from"./CZZfhpmp.js";const s={};function c(e,a){return r(),t("strong",null,[n(e.$slots,"default")])}const f=o(s,[["render",c]]);export{f as default}; +import{m as o,o as r,c as t,a8 as n}from"./K1dcBiIN.js";const s={};function c(e,a){return r(),t("strong",null,[n(e.$slots,"default")])}const f=o(s,[["render",c]]);export{f as default}; diff --git a/_nuxt/BoZ9Gzu9.js b/_nuxt/BoZ9Gzu9.js deleted file mode 100644 index 6fba0005..00000000 --- a/_nuxt/BoZ9Gzu9.js +++ /dev/null @@ -1 +0,0 @@ -import{d as p,I as f,k as i,o as t,c as s,a as u,a8 as n}from"./CZZfhpmp.js";const l=["id"],d=["href"],_=p({__name:"ProseH6",props:{id:{}},setup(r){const a=r,{headings:o}=f().public.mdc,c=i(()=>{var e;return a.id&&(typeof(o==null?void 0:o.anchorLinks)=="boolean"&&(o==null?void 0:o.anchorLinks)===!0||typeof(o==null?void 0:o.anchorLinks)=="object"&&((e=o==null?void 0:o.anchorLinks)==null?void 0:e.h6))});return(e,k)=>(t(),s("h6",{id:e.id},[e.id&&u(c)?(t(),s("a",{key:0,href:`#${e.id}`},[n(e.$slots,"default")],8,d)):n(e.$slots,"default",{key:1})],8,l))}});export{_ as default}; diff --git a/_nuxt/BqhY8_CC.js b/_nuxt/BqhY8_CC.js new file mode 100644 index 00000000..503e32e6 --- /dev/null +++ b/_nuxt/BqhY8_CC.js @@ -0,0 +1 @@ +import{c as s,b as t,F as d,r as l,o,t as r,h as a}from"./K1dcBiIN.js";const u={class:"container mx-auto font-mono text-white"},_=t("h1",{class:"my-6 text-2xl font-extrabold"},"Talks",-1),p={class:"grid grid-cols-10 gap-y-6"},g={class:"col-span-2"},m={class:"col-span-8"},f={class:"flex-col space-y-2"},v={class:"text-orange-500"},b={class:"flex"},x=["href"],y=["href"],D=["href"],S={__name:"talks",setup(w){const c=[{title:"Dagster Deep Dive",subtitle:"Orchestrating ML Workloads with Dagster & Modal",date:new Date("2024-9-24"),href_slides:"https://github.com/dagster-io/talks/blob/main/slides/deep-dive-dagster-modal-demo.pdf",href_code:"https://github.com/dagster-io/dagster-modal-demo"},{title:"Dagster Deep Dive",subtitle:"Data Quality: Building Reliable Data Platforms",date:new Date("2024-08-06"),href_slides:"https://github.com/dagster-io/talks/blob/main/slides/deep-dive-data-quality.pdf",href_video:"https://www.youtube.com/watch?v=vT0sSKEPE3A"},{title:"MotherDuck and Dagster",subtitle:"From local development to production",date:new Date("2024-04-18"),href_slides:"https://github.com/dagster-io/talks/blob/main/slides/motherduck-dagster-evidence-hybrid-compute.pdf",href_video:"https://www.youtube.com/watch?v=cOSiMMb_rjk",href_code:"https://github.com/dagster-io/talks/tree/main/motherduck-dagster-hybrid-compute"},{title:"Dagster Deep Dive",subtitle:"Configurations and Resources",date:new Date("2024-03-05"),href_slides:"https://github.com/dagster-io/talks/blob/main/slides/02-deep-dive-resources.pdf",href_video:"https://www.youtube.com/watch?v=i6m7k16W-yg",href_code:"https://github.com/dagster-io/talks/tree/main/dagster-deep-dives/dagster_deep_dives/resources_and_configurations"}],h=function(i){return i.toLocaleDateString("en-US",{month:"short",day:"2-digit",year:"numeric"})};return(i,k)=>(o(),s("div",u,[_,t("div",p,[(o(),s(d,null,l(c,(e,n)=>(o(),s(d,{key:n},[t("div",g,r(h(e.date)),1),t("div",m,[t("div",f,[t("div",v,r(e.title),1),t("div",null,r(e.subtitle),1),t("div",b,[e.href_slides?(o(),s("a",{key:0,class:"text-xs uppercase text-gray-400 hover:cursor-pointer hover:text-orange-500",href:e.href_slides}," [slide_deck] ",8,x)):a("",!0),e.href_video?(o(),s("a",{key:1,class:"text-xs uppercase text-gray-400 hover:cursor-pointer hover:text-orange-500",href:e.href_video}," [video] ",8,y)):a("",!0),e.href_code?(o(),s("a",{key:2,class:"text-xs uppercase text-gray-400 hover:cursor-pointer hover:text-orange-500",href:e.href_code}," [source_code] ",8,D)):a("",!0)])])])],64))),64))])]))}};export{S as default}; diff --git a/_nuxt/BwID1M5A.js b/_nuxt/BwID1M5A.js new file mode 100644 index 00000000..8bcc6b75 --- /dev/null +++ b/_nuxt/BwID1M5A.js @@ -0,0 +1 @@ +import{a6 as _,U as W,ab as B,I as M,Q as T,O as J}from"./K1dcBiIN.js";import{g as k,a as j,b as E,o as H,c as b,d as $,f as P,h as D,i as G}from"./Ce34VGij.js";import{p as Z}from"./C-v3KzvZ.js";import{u as N}from"./NnUIAPGH.js";import"./DvDH6DOc.js";const q="memory",F=()=>{const t=new Map;return{name:q,options:{},hasItem(r){return t.has(r)},getItem(r){return t.get(r)??null},getItemRaw(r){return t.get(r)??null},setItem(r,n){t.set(r,n)},setItemRaw(r,n){t.set(r,n)},removeItem(r){t.delete(r)},getKeys(){return Array.from(t.keys())},clear(){t.clear()},dispose(){t.clear()}}};function V(t){return!t||typeof t.then!="function"?Promise.resolve(t):t}function p(t,...r){try{return V(t(...r))}catch(n){return Promise.reject(n)}}function Q(t){const r=typeof t;return t===null||r!=="object"&&r!=="function"}function X(t){const r=Object.getPrototypeOf(t);return!r||r.isPrototypeOf(Object)}function K(t){if(Q(t))return String(t);if(X(t)||Array.isArray(t))return JSON.stringify(t);if(typeof t.toJSON=="function")return K(t.toJSON());throw new Error("[unstorage] Cannot stringify value!")}function z(){if(typeof Buffer===void 0)throw new TypeError("[unstorage] Buffer is not supported!")}const R="base64:";function ee(t){if(typeof t=="string")return t;z();const r=Buffer.from(t).toString("base64");return R+r}function te(t){return typeof t!="string"||!t.startsWith(R)?t:(z(),Buffer.from(t.slice(R.length),"base64"))}const re=["hasItem","getItem","getItemRaw","setItem","setItemRaw","removeItem","getMeta","setMeta","removeMeta","getKeys","clear","mount","unmount"];function ne(t,r){if(r=A(r),!r)return t;const n={...t};for(const a of re)n[a]=(l="",...c)=>t[a](r+l,...c);return n.getKeys=(a="",...l)=>t.getKeys(r+a,...l).then(c=>c.map(o=>o.slice(r.length))),n}function d(t){return t?t.split("?")[0].replace(/[/\\]/g,":").replace(/:+/g,":").replace(/^:|:$/g,""):""}function ie(...t){return d(t.join(":"))}function A(t){return t=d(t),t?t+":":""}const ae="memory",se=()=>{const t=new Map;return{name:ae,options:{},hasItem(r){return t.has(r)},getItem(r){return t.get(r)??null},getItemRaw(r){return t.get(r)??null},setItem(r,n){t.set(r,n)},setItemRaw(r,n){t.set(r,n)},removeItem(r){t.delete(r)},getKeys(){return Array.from(t.keys())},clear(){t.clear()},dispose(){t.clear()}}};function oe(t={}){const r={mounts:{"":t.driver||se()},mountpoints:[""],watching:!1,watchListeners:[],unwatch:{}},n=e=>{for(const i of r.mountpoints)if(e.startsWith(i))return{base:i,relativeKey:e.slice(i.length),driver:r.mounts[i]};return{base:"",relativeKey:e,driver:r.mounts[""]}},a=(e,i)=>r.mountpoints.filter(s=>s.startsWith(e)||i&&e.startsWith(s)).map(s=>({relativeBase:e.length>s.length?e.slice(s.length):void 0,mountpoint:s,driver:r.mounts[s]})),l=(e,i)=>{if(r.watching){i=d(i);for(const s of r.watchListeners)s(e,i)}},c=async()=>{if(!r.watching){r.watching=!0;for(const e in r.mounts)r.unwatch[e]=await x(r.mounts[e],l,e)}},o=async()=>{if(r.watching){for(const e in r.unwatch)await r.unwatch[e]();r.unwatch={},r.watching=!1}},h=(e,i,s)=>{const u=new Map,f=m=>{let y=u.get(m.base);return y||(y={driver:m.driver,base:m.base,items:[]},u.set(m.base,y)),y};for(const m of e){const y=typeof m=="string",v=d(y?m:m.key),w=y?void 0:m.value,I=y||!m.options?i:{...i,...m.options},O=n(v);f(O).items.push({key:v,value:w,relativeKey:O.relativeKey,options:I})}return Promise.all([...u.values()].map(m=>s(m))).then(m=>m.flat())},g={hasItem(e,i={}){e=d(e);const{relativeKey:s,driver:u}=n(e);return p(u.hasItem,s,i)},getItem(e,i={}){e=d(e);const{relativeKey:s,driver:u}=n(e);return p(u.getItem,s,i).then(f=>_(f))},getItems(e,i){return h(e,i,s=>s.driver.getItems?p(s.driver.getItems,s.items.map(u=>({key:u.relativeKey,options:u.options})),i).then(u=>u.map(f=>({key:ie(s.base,f.key),value:_(f.value)}))):Promise.all(s.items.map(u=>p(s.driver.getItem,u.relativeKey,u.options).then(f=>({key:u.key,value:_(f)})))))},getItemRaw(e,i={}){e=d(e);const{relativeKey:s,driver:u}=n(e);return u.getItemRaw?p(u.getItemRaw,s,i):p(u.getItem,s,i).then(f=>te(f))},async setItem(e,i,s={}){if(i===void 0)return g.removeItem(e);e=d(e);const{relativeKey:u,driver:f}=n(e);f.setItem&&(await p(f.setItem,u,K(i),s),f.watch||l("update",e))},async setItems(e,i){await h(e,i,async s=>{if(s.driver.setItems)return p(s.driver.setItems,s.items.map(u=>({key:u.relativeKey,value:K(u.value),options:u.options})),i);s.driver.setItem&&await Promise.all(s.items.map(u=>p(s.driver.setItem,u.relativeKey,K(u.value),u.options)))})},async setItemRaw(e,i,s={}){if(i===void 0)return g.removeItem(e,s);e=d(e);const{relativeKey:u,driver:f}=n(e);if(f.setItemRaw)await p(f.setItemRaw,u,i,s);else if(f.setItem)await p(f.setItem,u,ee(i),s);else return;f.watch||l("update",e)},async removeItem(e,i={}){typeof i=="boolean"&&(i={removeMeta:i}),e=d(e);const{relativeKey:s,driver:u}=n(e);u.removeItem&&(await p(u.removeItem,s,i),(i.removeMeta||i.removeMata)&&await p(u.removeItem,s+"$",i),u.watch||l("remove",e))},async getMeta(e,i={}){typeof i=="boolean"&&(i={nativeOnly:i}),e=d(e);const{relativeKey:s,driver:u}=n(e),f=Object.create(null);if(u.getMeta&&Object.assign(f,await p(u.getMeta,s,i)),!i.nativeOnly){const m=await p(u.getItem,s+"$",i).then(y=>_(y));m&&typeof m=="object"&&(typeof m.atime=="string"&&(m.atime=new Date(m.atime)),typeof m.mtime=="string"&&(m.mtime=new Date(m.mtime)),Object.assign(f,m))}return f},setMeta(e,i,s={}){return this.setItem(e+"$",i,s)},removeMeta(e,i={}){return this.removeItem(e+"$",i)},async getKeys(e,i={}){e=A(e);const s=a(e,!0);let u=[];const f=[];for(const m of s){const v=(await p(m.driver.getKeys,m.relativeBase,i)).map(w=>m.mountpoint+d(w)).filter(w=>!u.some(I=>w.startsWith(I)));f.push(...v),u=[m.mountpoint,...u.filter(w=>!w.startsWith(m.mountpoint))]}return e?f.filter(m=>m.startsWith(e)&&!m.endsWith("$")):f.filter(m=>!m.endsWith("$"))},async clear(e,i={}){e=A(e),await Promise.all(a(e,!1).map(async s=>{if(s.driver.clear)return p(s.driver.clear,s.relativeBase,i);if(s.driver.removeItem){const u=await s.driver.getKeys(s.relativeBase||"",i);return Promise.all(u.map(f=>s.driver.removeItem(f,i)))}}))},async dispose(){await Promise.all(Object.values(r.mounts).map(e=>L(e)))},async watch(e){return await c(),r.watchListeners.push(e),async()=>{r.watchListeners=r.watchListeners.filter(i=>i!==e),r.watchListeners.length===0&&await o()}},async unwatch(){r.watchListeners=[],await o()},mount(e,i){if(e=A(e),e&&r.mounts[e])throw new Error(`already mounted at ${e}`);return e&&(r.mountpoints.push(e),r.mountpoints.sort((s,u)=>u.length-s.length)),r.mounts[e]=i,r.watching&&Promise.resolve(x(i,l,e)).then(s=>{r.unwatch[e]=s}).catch(console.error),g},async unmount(e,i=!0){e=A(e),!(!e||!r.mounts[e])&&(r.watching&&e in r.unwatch&&(r.unwatch[e](),delete r.unwatch[e]),i&&await L(r.mounts[e]),r.mountpoints=r.mountpoints.filter(s=>s!==e),delete r.mounts[e])},getMount(e=""){e=d(e)+":";const i=n(e);return{driver:i.driver,base:i.base}},getMounts(e="",i={}){return e=d(e),a(e,i.parents).map(u=>({driver:u.driver,base:u.mountpoint}))}};return g}function x(t,r,n){return t.watch?t.watch((a,l)=>r(a,n+l)):()=>{}}async function L(t){typeof t.dispose=="function"&&await p(t.dispose)}function ue(t={}){const r=ce(n,t.operators);function n(a,l){return typeof l!="object"||l instanceof RegExp?r.$eq(a,l):Object.keys(l||{}).every(c=>{const o=l[c];if(c.startsWith("$")&&r[c]){const h=r[c];return typeof h=="function"?h(a,o):!1}return n(k(a,c),o)})}return n}function ce(t,r={}){return{$match:(n,a)=>t(n,a),$eq:(n,a)=>a instanceof RegExp?a.test(n):n===a,$ne:(n,a)=>a instanceof RegExp?!a.test(n):n!==a,$not:(n,a)=>!t(n,a),$and:(n,a)=>(j(a,"$and requires an array as condition"),a.every(l=>t(n,l))),$or:(n,a)=>(j(a,"$or requires an array as condition"),a.some(l=>t(n,l))),$in:(n,a)=>E(a).some(l=>Array.isArray(n)?t(n,{$contains:l}):t(n,l)),$contains:(n,a)=>(n=Array.isArray(n)?n:String(n),E(a).every(l=>n.includes(l))),$icontains:(n,a)=>{if(typeof a!="string")throw new TypeError("$icontains requires a string, use $contains instead");return n=String(n).toLocaleLowerCase(),E(a).every(l=>n.includes(l.toLocaleLowerCase()))},$containsAny:(n,a)=>(j(a,"$containsAny requires an array as condition"),n=Array.isArray(n)?n:String(n),a.some(l=>n.includes(l))),$exists:(n,a)=>a?typeof n<"u":typeof n>"u",$type:(n,a)=>typeof n===String(a),$regex:(n,a)=>{if(!(a instanceof RegExp)){const l=String(a).match(/\/(.*)\/([dgimsuy]*)$/);a=l?new RegExp(l[1],l[2]||""):new RegExp(a)}return a.test(String(n||""))},$lt:(n,a)=>nn<=a,$gt:(n,a)=>n>a,$gte:(n,a)=>n>=a,...r||{}}}function le(t){const r=ue(),n=(c,{query:o,before:h,after:g})=>{const e=typeof o=="string"?{_path:o}:o,i=c.findIndex(u=>r(u,e));h=h??1,g=g??1;const s=new Array(h+g).fill(null,0);return i===-1?s:s.map((u,f)=>c[i-h+f+ +(f>=h)]||null)},a=[(c,o)=>{const h=c.result.filter(g=>E(o.where).every(e=>r(g,e)));return{...c,result:h,total:h.length}},(c,o)=>E(o.sort).forEach(h=>b(c.result,h)),function(o,h,g){var e;if(h.surround){let i=n(((e=o.result)==null?void 0:e.length)===1?g:o.result,h.surround);i=$(P(h.without))(i),i=$(D(h.only))(i),o.surround=i}return o}],l=[(c,o)=>{if(o.skip)return{...c,result:c.result.slice(o.skip),skip:o.skip}},(c,o)=>{if(o.limit)return{...c,result:c.result.slice(0,o.limit),limit:o.limit}},function(o,h,g){var e,i,s;if(h.dirConfig){const u=((e=o.result[0])==null?void 0:e._path)||((s=(i=h.where)==null?void 0:i.find(f=>f._path))==null?void 0:s._path);if(typeof u=="string"){const f=g.find(m=>m._path===W(u,"_dir"));f&&(o.dirConfig={_path:f._path,...P(["_"])(f)})}}return o},(c,o)=>({...c,result:$(P(o.without))(c.result)}),(c,o)=>({...c,result:$(D(o.only))(c.result)})];return async c=>{const o=await t(),h=c.params(),g={result:o,limit:0,skip:0,total:o.length},e=a.reduce((s,u)=>u(s,h,o)||s,g);if(h.count)return{result:e.result.length};const i=l.reduce((s,u)=>u(s,h,o)||s,e);return h.first?{...H(["skip","limit","total"])(i),result:i.result[0]}:i}}function U(t){const r=le(t);return async n=>{var c;n.params().first&&n.withDirConfig();const a=n.params(),l=await r(n);return a.surround?l==null?void 0:l.surround:(l!=null&&l.dirConfig&&(l.result={_path:(c=l.dirConfig)==null?void 0:c._path,...l.result,_dir:l.dirConfig}),l==null?void 0:l.result)}}var fe={exports:{}};(function(t,r){(function(n,a,l){t.exports=l(),t.exports.default=l()})("slugify",B,function(){var n=JSON.parse(`{"$":"dollar","%":"percent","&":"and","<":"less",">":"greater","|":"or","¢":"cent","£":"pound","¤":"currency","¥":"yen","©":"(c)","ª":"a","®":"(r)","º":"o","À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","Æ":"AE","Ç":"C","È":"E","É":"E","Ê":"E","Ë":"E","Ì":"I","Í":"I","Î":"I","Ï":"I","Ð":"D","Ñ":"N","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","Ù":"U","Ú":"U","Û":"U","Ü":"U","Ý":"Y","Þ":"TH","ß":"ss","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","æ":"ae","ç":"c","è":"e","é":"e","ê":"e","ë":"e","ì":"i","í":"i","î":"i","ï":"i","ð":"d","ñ":"n","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","ù":"u","ú":"u","û":"u","ü":"u","ý":"y","þ":"th","ÿ":"y","Ā":"A","ā":"a","Ă":"A","ă":"a","Ą":"A","ą":"a","Ć":"C","ć":"c","Č":"C","č":"c","Ď":"D","ď":"d","Đ":"DJ","đ":"dj","Ē":"E","ē":"e","Ė":"E","ė":"e","Ę":"e","ę":"e","Ě":"E","ě":"e","Ğ":"G","ğ":"g","Ģ":"G","ģ":"g","Ĩ":"I","ĩ":"i","Ī":"i","ī":"i","Į":"I","į":"i","İ":"I","ı":"i","Ķ":"k","ķ":"k","Ļ":"L","ļ":"l","Ľ":"L","ľ":"l","Ł":"L","ł":"l","Ń":"N","ń":"n","Ņ":"N","ņ":"n","Ň":"N","ň":"n","Ō":"O","ō":"o","Ő":"O","ő":"o","Œ":"OE","œ":"oe","Ŕ":"R","ŕ":"r","Ř":"R","ř":"r","Ś":"S","ś":"s","Ş":"S","ş":"s","Š":"S","š":"s","Ţ":"T","ţ":"t","Ť":"T","ť":"t","Ũ":"U","ũ":"u","Ū":"u","ū":"u","Ů":"U","ů":"u","Ű":"U","ű":"u","Ų":"U","ų":"u","Ŵ":"W","ŵ":"w","Ŷ":"Y","ŷ":"y","Ÿ":"Y","Ź":"Z","ź":"z","Ż":"Z","ż":"z","Ž":"Z","ž":"z","Ə":"E","ƒ":"f","Ơ":"O","ơ":"o","Ư":"U","ư":"u","Lj":"LJ","lj":"lj","Nj":"NJ","nj":"nj","Ș":"S","ș":"s","Ț":"T","ț":"t","ə":"e","˚":"o","Ά":"A","Έ":"E","Ή":"H","Ί":"I","Ό":"O","Ύ":"Y","Ώ":"W","ΐ":"i","Α":"A","Β":"B","Γ":"G","Δ":"D","Ε":"E","Ζ":"Z","Η":"H","Θ":"8","Ι":"I","Κ":"K","Λ":"L","Μ":"M","Ν":"N","Ξ":"3","Ο":"O","Π":"P","Ρ":"R","Σ":"S","Τ":"T","Υ":"Y","Φ":"F","Χ":"X","Ψ":"PS","Ω":"W","Ϊ":"I","Ϋ":"Y","ά":"a","έ":"e","ή":"h","ί":"i","ΰ":"y","α":"a","β":"b","γ":"g","δ":"d","ε":"e","ζ":"z","η":"h","θ":"8","ι":"i","κ":"k","λ":"l","μ":"m","ν":"n","ξ":"3","ο":"o","π":"p","ρ":"r","ς":"s","σ":"s","τ":"t","υ":"y","φ":"f","χ":"x","ψ":"ps","ω":"w","ϊ":"i","ϋ":"y","ό":"o","ύ":"y","ώ":"w","Ё":"Yo","Ђ":"DJ","Є":"Ye","І":"I","Ї":"Yi","Ј":"J","Љ":"LJ","Њ":"NJ","Ћ":"C","Џ":"DZ","А":"A","Б":"B","В":"V","Г":"G","Д":"D","Е":"E","Ж":"Zh","З":"Z","И":"I","Й":"J","К":"K","Л":"L","М":"M","Н":"N","О":"O","П":"P","Р":"R","С":"S","Т":"T","У":"U","Ф":"F","Х":"H","Ц":"C","Ч":"Ch","Ш":"Sh","Щ":"Sh","Ъ":"U","Ы":"Y","Ь":"","Э":"E","Ю":"Yu","Я":"Ya","а":"a","б":"b","в":"v","г":"g","д":"d","е":"e","ж":"zh","з":"z","и":"i","й":"j","к":"k","л":"l","м":"m","н":"n","о":"o","п":"p","р":"r","с":"s","т":"t","у":"u","ф":"f","х":"h","ц":"c","ч":"ch","ш":"sh","щ":"sh","ъ":"u","ы":"y","ь":"","э":"e","ю":"yu","я":"ya","ё":"yo","ђ":"dj","є":"ye","і":"i","ї":"yi","ј":"j","љ":"lj","њ":"nj","ћ":"c","ѝ":"u","џ":"dz","Ґ":"G","ґ":"g","Ғ":"GH","ғ":"gh","Қ":"KH","қ":"kh","Ң":"NG","ң":"ng","Ү":"UE","ү":"ue","Ұ":"U","ұ":"u","Һ":"H","һ":"h","Ә":"AE","ә":"ae","Ө":"OE","ө":"oe","Ա":"A","Բ":"B","Գ":"G","Դ":"D","Ե":"E","Զ":"Z","Է":"E'","Ը":"Y'","Թ":"T'","Ժ":"JH","Ի":"I","Լ":"L","Խ":"X","Ծ":"C'","Կ":"K","Հ":"H","Ձ":"D'","Ղ":"GH","Ճ":"TW","Մ":"M","Յ":"Y","Ն":"N","Շ":"SH","Չ":"CH","Պ":"P","Ջ":"J","Ռ":"R'","Ս":"S","Վ":"V","Տ":"T","Ր":"R","Ց":"C","Փ":"P'","Ք":"Q'","Օ":"O''","Ֆ":"F","և":"EV","ء":"a","آ":"aa","أ":"a","ؤ":"u","إ":"i","ئ":"e","ا":"a","ب":"b","ة":"h","ت":"t","ث":"th","ج":"j","ح":"h","خ":"kh","د":"d","ذ":"th","ر":"r","ز":"z","س":"s","ش":"sh","ص":"s","ض":"dh","ط":"t","ظ":"z","ع":"a","غ":"gh","ف":"f","ق":"q","ك":"k","ل":"l","م":"m","ن":"n","ه":"h","و":"w","ى":"a","ي":"y","ً":"an","ٌ":"on","ٍ":"en","َ":"a","ُ":"u","ِ":"e","ْ":"","٠":"0","١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","پ":"p","چ":"ch","ژ":"zh","ک":"k","گ":"g","ی":"y","۰":"0","۱":"1","۲":"2","۳":"3","۴":"4","۵":"5","۶":"6","۷":"7","۸":"8","۹":"9","฿":"baht","ა":"a","ბ":"b","გ":"g","დ":"d","ე":"e","ვ":"v","ზ":"z","თ":"t","ი":"i","კ":"k","ლ":"l","მ":"m","ნ":"n","ო":"o","პ":"p","ჟ":"zh","რ":"r","ს":"s","ტ":"t","უ":"u","ფ":"f","ქ":"k","ღ":"gh","ყ":"q","შ":"sh","ჩ":"ch","ც":"ts","ძ":"dz","წ":"ts","ჭ":"ch","ხ":"kh","ჯ":"j","ჰ":"h","Ṣ":"S","ṣ":"s","Ẁ":"W","ẁ":"w","Ẃ":"W","ẃ":"w","Ẅ":"W","ẅ":"w","ẞ":"SS","Ạ":"A","ạ":"a","Ả":"A","ả":"a","Ấ":"A","ấ":"a","Ầ":"A","ầ":"a","Ẩ":"A","ẩ":"a","Ẫ":"A","ẫ":"a","Ậ":"A","ậ":"a","Ắ":"A","ắ":"a","Ằ":"A","ằ":"a","Ẳ":"A","ẳ":"a","Ẵ":"A","ẵ":"a","Ặ":"A","ặ":"a","Ẹ":"E","ẹ":"e","Ẻ":"E","ẻ":"e","Ẽ":"E","ẽ":"e","Ế":"E","ế":"e","Ề":"E","ề":"e","Ể":"E","ể":"e","Ễ":"E","ễ":"e","Ệ":"E","ệ":"e","Ỉ":"I","ỉ":"i","Ị":"I","ị":"i","Ọ":"O","ọ":"o","Ỏ":"O","ỏ":"o","Ố":"O","ố":"o","Ồ":"O","ồ":"o","Ổ":"O","ổ":"o","Ỗ":"O","ỗ":"o","Ộ":"O","ộ":"o","Ớ":"O","ớ":"o","Ờ":"O","ờ":"o","Ở":"O","ở":"o","Ỡ":"O","ỡ":"o","Ợ":"O","ợ":"o","Ụ":"U","ụ":"u","Ủ":"U","ủ":"u","Ứ":"U","ứ":"u","Ừ":"U","ừ":"u","Ử":"U","ử":"u","Ữ":"U","ữ":"u","Ự":"U","ự":"u","Ỳ":"Y","ỳ":"y","Ỵ":"Y","ỵ":"y","Ỷ":"Y","ỷ":"y","Ỹ":"Y","ỹ":"y","–":"-","‘":"'","’":"'","“":"\\"","”":"\\"","„":"\\"","†":"+","•":"*","…":"...","₠":"ecu","₢":"cruzeiro","₣":"french franc","₤":"lira","₥":"mill","₦":"naira","₧":"peseta","₨":"rupee","₩":"won","₪":"new shequel","₫":"dong","€":"euro","₭":"kip","₮":"tugrik","₯":"drachma","₰":"penny","₱":"peso","₲":"guarani","₳":"austral","₴":"hryvnia","₵":"cedi","₸":"kazakhstani tenge","₹":"indian rupee","₺":"turkish lira","₽":"russian ruble","₿":"bitcoin","℠":"sm","™":"tm","∂":"d","∆":"delta","∑":"sum","∞":"infinity","♥":"love","元":"yuan","円":"yen","﷼":"rial","ﻵ":"laa","ﻷ":"laa","ﻹ":"lai","ﻻ":"la"}`),a=JSON.parse('{"bg":{"Й":"Y","Ц":"Ts","Щ":"Sht","Ъ":"A","Ь":"Y","й":"y","ц":"ts","щ":"sht","ъ":"a","ь":"y"},"de":{"Ä":"AE","ä":"ae","Ö":"OE","ö":"oe","Ü":"UE","ü":"ue","ß":"ss","%":"prozent","&":"und","|":"oder","∑":"summe","∞":"unendlich","♥":"liebe"},"es":{"%":"por ciento","&":"y","<":"menor que",">":"mayor que","|":"o","¢":"centavos","£":"libras","¤":"moneda","₣":"francos","∑":"suma","∞":"infinito","♥":"amor"},"fr":{"%":"pourcent","&":"et","<":"plus petit",">":"plus grand","|":"ou","¢":"centime","£":"livre","¤":"devise","₣":"franc","∑":"somme","∞":"infini","♥":"amour"},"pt":{"%":"porcento","&":"e","<":"menor",">":"maior","|":"ou","¢":"centavo","∑":"soma","£":"libra","∞":"infinito","♥":"amor"},"uk":{"И":"Y","и":"y","Й":"Y","й":"y","Ц":"Ts","ц":"ts","Х":"Kh","х":"kh","Щ":"Shch","щ":"shch","Г":"H","г":"h"},"vi":{"Đ":"D","đ":"d"},"da":{"Ø":"OE","ø":"oe","Å":"AA","å":"aa","%":"procent","&":"og","|":"eller","$":"dollar","<":"mindre end",">":"større end"},"nb":{"&":"og","Å":"AA","Æ":"AE","Ø":"OE","å":"aa","æ":"ae","ø":"oe"},"it":{"&":"e"},"nl":{"&":"en"},"sv":{"&":"och","Å":"AA","Ä":"AE","Ö":"OE","å":"aa","ä":"ae","ö":"oe"}}');function l(c,o){if(typeof c!="string")throw new Error("slugify: string argument expected");o=typeof o=="string"?{replacement:o}:o||{};var h=a[o.locale]||{},g=o.replacement===void 0?"-":o.replacement,e=o.trim===void 0?!0:o.trim,i=c.normalize().split("").reduce(function(s,u){var f=h[u];return f===void 0&&(f=n[u]),f===void 0&&(f=u),f===g&&(f=" "),s+f.replace(o.remove||/[^\w\s$*_+~.()'"!\-:@]+/g,"")},"");return o.strict&&(i=i.replace(/[^A-Za-z0-9\s]/g,"")),e&&(i=i.trim()),i=i.replace(/\s+/g,g),o.lower&&(i=i.toLowerCase()),i}return l.extend=function(c){Object.assign(n,c)},l})})(fe);const me=t=>t.split(/[\s-]/g).map(Z).join(" ");function he(t,r){const{navigation:n}=M().public.content;if(n===!1)return[];const a=c=>({...pe(["title",...n.fields])(c),...de(c==null?void 0:c.navigation)?c.navigation:{}}),l=t.sort((c,o)=>c._path.localeCompare(o._path)).reduce((c,o)=>{const h=o._path.substring(1).split("/"),g=o._id.split(":").slice(1),e=!!g[g.length-1].match(/([1-9][0-9]*\.)?index.md/g),i=f=>({title:f.title,_path:f._path,_file:f._file,children:[],...a(f),...f._draft?{_draft:!0}:{}}),s=i(o);if(e){const f=r[s._path];if(typeof(f==null?void 0:f.navigation)<"u"&&!(f!=null&&f.navigation))return c;if(o._path!=="/"){const m=i(o);s.children.push(m)}Object.assign(s,a(f))}return h.length===1?(c.push(s),c):(h.slice(0,-1).reduce((f,m,y)=>{const v="/"+h.slice(0,y+1).join("/"),w=r[v];if(typeof(w==null?void 0:w.navigation)<"u"&&!w.navigation)return[];let I=f.find(O=>O._path===v);return I||(I={title:me(m),_path:v,_file:o._file,children:[],...a(w)},f.push(I)),I.children},c).push(s),c)},[]);return Y(l)}const ge=new Intl.Collator(void 0,{numeric:!0,sensitivity:"base"});function Y(t){var n;t.forEach(a=>{a._file=a._file.split(".").slice(0,-1).join(".")});const r=t.sort((a,l)=>ge.compare(a._file,l._file));for(const a of r)(n=a.children)!=null&&n.length?Y(a.children):delete a.children,delete a._file;return t}function pe(t){return r=>(r=r||{},t&&t.length?t.filter(n=>typeof r[n]<"u").reduce((n,a)=>Object.assign(n,{[a]:r[a]}),{}):r)}function de(t){return Object.prototype.toString.call(t)==="[object Object]"}const ye=t=>T(t,M().public.content.api.baseURL),we=ne(oe({driver:F()}),"@content");function ve(t){async function r(){const n=new Set(await t.getKeys("cache:")),a=N().getPreviewToken();if(a){const c=await t.getItem(`${a}$`).then(g=>g||{});if(Array.isArray(c.ignoreSources)){const g=c.ignoreSources.map(e=>`cache:${e.trim()}:`);for(const e of n)g.some(i=>e.startsWith(i))&&n.delete(e)}const o=await t.getKeys(`${a}:`),h=await Promise.all(o.map(g=>t.getItem(g)));for(const g of h)n.delete(`cache:${g._id}`),g.__deleted||n.add(`${a}:${g._id}`)}return await Promise.all(Array.from(n).map(c=>t.getItem(c)))}return{storage:t,fetch:U(r),query:n=>G(U(r),{initialParams:n,legacy:!0})}}let C=null,S=null;async function Ie(){return S?await S:C||(S=Ae(),C=await S),C}async function Ae(){const t=J(),{content:r}=M().public,n=ve(we),a=await n.storage.getItem("integrity");if(r.integrity!==+(a||0)){const{contents:l,navigation:c}=await $fetch(ye(r.integrity?`cache.${r.integrity}.json`:"cache.json"));await Promise.all(l.map(o=>n.storage.setItem(`cache:${o._id}`,o))),await n.storage.setItem("navigation",c),await n.storage.setItem("integrity",r.integrity)}return await t.callHook("content:storage",n.storage),n}async function Ke(t){const r=await Ie();if(!N().getPreviewToken()&&Object.keys(t||{}).length===0)return r.storage.getItem("navigation");const n=await r.query(t).where({_partial:!1,navigation:{$ne:!1}}).find(),l=(await r.query().where({_path:/\/_dir$/i,_partial:!0}).find()).reduce((c,o)=>{var g;((g=o.title)==null?void 0:g.toLowerCase())==="dir"&&(o.title=void 0);const h=o._path.split("/").slice(0,-1).join("/")||"/";return c[h]={...o,...o.body},c},{});return he(n,l)}export{we as contentStorage,ve as createDB,Ke as generateNavigation,Ie as useContentDatabase}; diff --git a/_nuxt/Oa1zqAZH.js b/_nuxt/BwySm3O-.js similarity index 64% rename from _nuxt/Oa1zqAZH.js rename to _nuxt/BwySm3O-.js index 9b563790..d1effb9d 100644 --- a/_nuxt/Oa1zqAZH.js +++ b/_nuxt/BwySm3O-.js @@ -1 +1 @@ -import{m as o,o as r,c as t,a8 as s}from"./CZZfhpmp.js";const c={};function n(e,a){return r(),t("td",null,[s(e.$slots,"default")])}const d=o(c,[["render",n]]);export{d as default}; +import{m as o,o as r,c as t,a8 as s}from"./K1dcBiIN.js";const c={};function n(e,a){return r(),t("td",null,[s(e.$slots,"default")])}const d=o(c,[["render",n]]);export{d as default}; diff --git a/_nuxt/C-6Jpe-m.js b/_nuxt/C-6Jpe-m.js new file mode 100644 index 00000000..83c8660c --- /dev/null +++ b/_nuxt/C-6Jpe-m.js @@ -0,0 +1 @@ +import{d as i,I as c,k as p,o as s,c as n,a as u,a8 as t}from"./K1dcBiIN.js";const f=["id"],l=["href"],k=i({__name:"ProseH5",props:{id:{}},setup(a){const r=a,{headings:o}=c().public.mdc,d=p(()=>{var e;return r.id&&((e=o==null?void 0:o.anchorLinks)==null?void 0:e.h5)});return(e,m)=>(s(),n("h5",{id:e.id},[e.id&&u(d)?(s(),n("a",{key:0,href:`#${e.id}`},[t(e.$slots,"default")],8,l)):t(e.$slots,"default",{key:1})],8,f))}});export{k as default}; diff --git a/_nuxt/C67JdZ9D.js b/_nuxt/C67JdZ9D.js new file mode 100644 index 00000000..a37c6cc7 --- /dev/null +++ b/_nuxt/C67JdZ9D.js @@ -0,0 +1 @@ +import{d as i,I as c,k as p,o as s,c as n,a as u,a8 as t}from"./K1dcBiIN.js";const f=["id"],l=["href"],k=i({__name:"ProseH4",props:{id:{}},setup(a){const r=a,{headings:o}=c().public.mdc,d=p(()=>{var e;return r.id&&((e=o==null?void 0:o.anchorLinks)==null?void 0:e.h4)});return(e,m)=>(s(),n("h4",{id:e.id},[e.id&&u(d)?(s(),n("a",{key:0,href:`#${e.id}`},[t(e.$slots,"default")],8,l)):t(e.$slots,"default",{key:1})],8,f))}});export{k as default}; diff --git a/_nuxt/BT7WDeVb.js b/_nuxt/C6WZwVE2.js similarity index 97% rename from _nuxt/BT7WDeVb.js rename to _nuxt/C6WZwVE2.js index 4d26826a..e1949b28 100644 --- a/_nuxt/BT7WDeVb.js +++ b/_nuxt/C6WZwVE2.js @@ -1 +1 @@ -import{W as C,j as y,X as w,N as b,Y as O,y as B,v as M,Z as _,O as E,$ as H,a as R,a0 as S,a1 as j}from"./CZZfhpmp.js";const z=s=>s==="defer"||s===!1;function F(...s){var m;const i=typeof s[s.length-1]=="string"?s.pop():void 0;typeof s[0]!="string"&&s.unshift(i);let[t,u,a={}]=s;if(typeof t!="string")throw new TypeError("[nuxt] [asyncData] key must be a string.");if(typeof u!="function")throw new TypeError("[nuxt] [asyncData] handler must be a function.");const e=E(),v=u,p=()=>null,g=()=>e.isHydrating?e.payload.data[t]:e.static.data[t];a.server=a.server??!0,a.default=a.default??p,a.getCachedData=a.getCachedData??g,a.lazy=a.lazy??!1,a.immediate=a.immediate??!0,a.deep=a.deep??C.deep,a.dedupe=a.dedupe??"cancel";const d=()=>a.getCachedData(t,e)!=null;if(!e._asyncData[t]||!a.immediate){(m=e.payload._errors)[t]??(m[t]=null);const o=a.deep?y:w;e._asyncData[t]={data:o(a.getCachedData(t,e)??a.default()),pending:y(!d()),error:b(e.payload._errors,t),status:y("idle")}}const r={...e._asyncData[t]};r.refresh=r.execute=(o={})=>{if(e._asyncDataPromises[t]){if(z(o.dedupe??a.dedupe))return e._asyncDataPromises[t];e._asyncDataPromises[t].cancelled=!0}if((o._initial||e.isHydrating&&o._initial!==!1)&&d())return Promise.resolve(a.getCachedData(t,e));r.pending.value=!0,r.status.value="pending";const l=new Promise((c,n)=>{try{c(v(e))}catch(f){n(f)}}).then(async c=>{if(l.cancelled)return e._asyncDataPromises[t];let n=c;a.transform&&(n=await a.transform(c)),a.pick&&(n=K(n,a.pick)),e.payload.data[t]=n,r.data.value=n,r.error.value=null,r.status.value="success"}).catch(c=>{if(l.cancelled)return e._asyncDataPromises[t];r.error.value=H(c),r.data.value=R(a.default()),r.status.value="error"}).finally(()=>{l.cancelled||(r.pending.value=!1,delete e._asyncDataPromises[t])});return e._asyncDataPromises[t]=l,e._asyncDataPromises[t]},r.clear=()=>N(e,t);const D=()=>r.refresh({_initial:!0}),P=a.server!==!1&&e.payload.serverRendered;{const o=S();if(o&&!o._nuxtOnBeforeMountCbs){o._nuxtOnBeforeMountCbs=[];const n=o._nuxtOnBeforeMountCbs;O(()=>{n.forEach(f=>{f()}),n.splice(0,n.length)}),B(()=>n.splice(0,n.length))}P&&e.isHydrating&&(r.error.value||d())?(r.pending.value=!1,r.status.value=r.error.value?"error":"success"):o&&(e.payload.serverRendered&&e.isHydrating||a.lazy)&&a.immediate?o._nuxtOnBeforeMountCbs.push(D):a.immediate&&D();const l=j();if(a.watch){const n=M(a.watch,()=>r.refresh());l&&_(n)}const c=e.hook("app:data:refresh",async n=>{(!n||n.includes(t))&&await r.refresh()});l&&_(c)}const h=Promise.resolve(e._asyncDataPromises[t]).then(()=>r);return Object.assign(h,r),h}function N(s,i){i in s.payload.data&&(s.payload.data[i]=void 0),i in s.payload._errors&&(s.payload._errors[i]=null),s._asyncData[i]&&(s._asyncData[i].data.value=void 0,s._asyncData[i].error.value=null,s._asyncData[i].pending.value=!1,s._asyncData[i].status.value="idle"),i in s._asyncDataPromises&&(s._asyncDataPromises[i].cancelled=!0,s._asyncDataPromises[i]=void 0)}function K(s,i){const t={};for(const u of i)t[u]=s[u];return t}export{F as u}; +import{W as C,j as y,X as w,N as b,Y as O,y as B,v as M,Z as _,O as E,$ as H,a as R,a0 as S,a1 as j}from"./K1dcBiIN.js";const z=s=>s==="defer"||s===!1;function F(...s){var m;const i=typeof s[s.length-1]=="string"?s.pop():void 0;typeof s[0]!="string"&&s.unshift(i);let[t,u,a={}]=s;if(typeof t!="string")throw new TypeError("[nuxt] [asyncData] key must be a string.");if(typeof u!="function")throw new TypeError("[nuxt] [asyncData] handler must be a function.");const e=E(),v=u,p=()=>null,g=()=>e.isHydrating?e.payload.data[t]:e.static.data[t];a.server=a.server??!0,a.default=a.default??p,a.getCachedData=a.getCachedData??g,a.lazy=a.lazy??!1,a.immediate=a.immediate??!0,a.deep=a.deep??C.deep,a.dedupe=a.dedupe??"cancel";const d=()=>a.getCachedData(t,e)!=null;if(!e._asyncData[t]||!a.immediate){(m=e.payload._errors)[t]??(m[t]=null);const o=a.deep?y:w;e._asyncData[t]={data:o(a.getCachedData(t,e)??a.default()),pending:y(!d()),error:b(e.payload._errors,t),status:y("idle")}}const r={...e._asyncData[t]};r.refresh=r.execute=(o={})=>{if(e._asyncDataPromises[t]){if(z(o.dedupe??a.dedupe))return e._asyncDataPromises[t];e._asyncDataPromises[t].cancelled=!0}if((o._initial||e.isHydrating&&o._initial!==!1)&&d())return Promise.resolve(a.getCachedData(t,e));r.pending.value=!0,r.status.value="pending";const l=new Promise((c,n)=>{try{c(v(e))}catch(f){n(f)}}).then(async c=>{if(l.cancelled)return e._asyncDataPromises[t];let n=c;a.transform&&(n=await a.transform(c)),a.pick&&(n=K(n,a.pick)),e.payload.data[t]=n,r.data.value=n,r.error.value=null,r.status.value="success"}).catch(c=>{if(l.cancelled)return e._asyncDataPromises[t];r.error.value=H(c),r.data.value=R(a.default()),r.status.value="error"}).finally(()=>{l.cancelled||(r.pending.value=!1,delete e._asyncDataPromises[t])});return e._asyncDataPromises[t]=l,e._asyncDataPromises[t]},r.clear=()=>N(e,t);const D=()=>r.refresh({_initial:!0}),P=a.server!==!1&&e.payload.serverRendered;{const o=S();if(o&&!o._nuxtOnBeforeMountCbs){o._nuxtOnBeforeMountCbs=[];const n=o._nuxtOnBeforeMountCbs;O(()=>{n.forEach(f=>{f()}),n.splice(0,n.length)}),B(()=>n.splice(0,n.length))}P&&e.isHydrating&&(r.error.value||d())?(r.pending.value=!1,r.status.value=r.error.value?"error":"success"):o&&(e.payload.serverRendered&&e.isHydrating||a.lazy)&&a.immediate?o._nuxtOnBeforeMountCbs.push(D):a.immediate&&D();const l=j();if(a.watch){const n=M(a.watch,()=>r.refresh());l&&_(n)}const c=e.hook("app:data:refresh",async n=>{(!n||n.includes(t))&&await r.refresh()});l&&_(c)}const h=Promise.resolve(e._asyncDataPromises[t]).then(()=>r);return Object.assign(h,r),h}function N(s,i){i in s.payload.data&&(s.payload.data[i]=void 0),i in s.payload._errors&&(s.payload._errors[i]=null),s._asyncData[i]&&(s._asyncData[i].data.value=void 0,s._asyncData[i].error.value=null,s._asyncData[i].pending.value=!1,s._asyncData[i].status.value="idle"),i in s._asyncDataPromises&&(s._asyncDataPromises[i].cancelled=!0,s._asyncDataPromises[i]=void 0)}function K(s,i){const t={};for(const u of i)t[u]=s[u];return t}export{F as u}; diff --git a/_nuxt/B25qHsMz.js b/_nuxt/CAu-wKXH.js similarity index 53% rename from _nuxt/B25qHsMz.js rename to _nuxt/CAu-wKXH.js index 0ca24a7e..529425ad 100644 --- a/_nuxt/B25qHsMz.js +++ b/_nuxt/CAu-wKXH.js @@ -1 +1 @@ -import{m as e,o as r,c}from"./CZZfhpmp.js";const o={};function t(n,s){return r(),c("hr")}const _=e(o,[["render",t]]);export{_ as default}; +import{m as e,o as r,c}from"./K1dcBiIN.js";const o={};function t(n,s){return r(),c("hr")}const _=e(o,[["render",t]]);export{_ as default}; diff --git a/_nuxt/CHuhJ_Er.js b/_nuxt/CHuhJ_Er.js new file mode 100644 index 00000000..69e3fb85 --- /dev/null +++ b/_nuxt/CHuhJ_Er.js @@ -0,0 +1 @@ +import{c as e,o as t,b as o}from"./K1dcBiIN.js";const s={class:"flex h-[1024px] justify-center border-2 border-gray-500"},c=o("iframe",{src:"https://cmpadden.github.io/conway/",width:"100%",height:"100%"},null,-1),a=[c],d={__name:"conway",setup(r){return(n,_)=>(t(),e("main",s,a))}};export{d as default}; diff --git a/_nuxt/CJD6qL-K.js b/_nuxt/CJD6qL-K.js deleted file mode 100644 index 7ddfddef..00000000 --- a/_nuxt/CJD6qL-K.js +++ /dev/null @@ -1 +0,0 @@ -import{d as p,I as f,k as i,o as t,c as s,a as u,a8 as n}from"./CZZfhpmp.js";const l=["id"],d=["href"],_=p({__name:"ProseH4",props:{id:{}},setup(r){const a=r,{headings:o}=f().public.mdc,c=i(()=>{var e;return a.id&&(typeof(o==null?void 0:o.anchorLinks)=="boolean"&&(o==null?void 0:o.anchorLinks)===!0||typeof(o==null?void 0:o.anchorLinks)=="object"&&((e=o==null?void 0:o.anchorLinks)==null?void 0:e.h4))});return(e,k)=>(t(),s("h4",{id:e.id},[e.id&&u(c)?(t(),s("a",{key:0,href:`#${e.id}`},[n(e.$slots,"default")],8,d)):n(e.$slots,"default",{key:1})],8,l))}});export{_ as default}; diff --git a/_nuxt/CM0LhmwP.js b/_nuxt/CM0LhmwP.js new file mode 100644 index 00000000..c6e2b836 --- /dev/null +++ b/_nuxt/CM0LhmwP.js @@ -0,0 +1 @@ +import{m as s,o as n,c,b as e,i as t,a8 as l,aa as d}from"./K1dcBiIN.js";const i={},f={class:"pin-b w-full p-4 text-xs font-bold text-white"},h=e("div",{class:"flex justify-center space-x-2"},[e("a",{class:"hover:cursor-pointer hover:text-blue-200",href:"https://github.com/cmpadden/cmpadden.github.io"}," © Colton Padden"),e("span",null,"•"),e("a",{class:"hover:cursor-pointer hover:text-blue-200",href:"/sitemap.xml"},"Sitemap"),e("span",null,"•"),e("a",{class:"hover:cursor-pointer hover:text-blue-200",href:"/atom"},"RSS")],-1),u=[h];function p(o,r){return n(),c("footer",f,u)}const m=s(i,[["render",p]]),x={},b={class:"bg-orange-500"},v={class:"rounded-3xl border-[10px] border-orange-500"},g={class:"flex min-h-screen flex-col rounded-3xl bg-background font-display"},$={class:"flex-1"};function S(o,r){const a=d,_=m;return n(),c("div",b,[e("div",v,[e("main",g,[t(a),e("main",$,[l(o.$slots,"default")]),t(_)])])])}const B=s(x,[["render",S]]);export{B as default}; diff --git a/_nuxt/CMGdJvMz.js b/_nuxt/CMGdJvMz.js deleted file mode 100644 index cd1da490..00000000 --- a/_nuxt/CMGdJvMz.js +++ /dev/null @@ -1 +0,0 @@ -import{u as A,j as g,w as R,k as m,c as r,b as o,F as d,r as v,a as i,h as S,o as l,t as p,i as f,f as h,g as D,l as C,_ as F}from"./CZZfhpmp.js";import{_ as L}from"./CuOPeUWs.js";import j from"./B1tmNyhF.js";import{u as z}from"./BT7WDeVb.js";import{q as E}from"./CmpoAw97.js";import"./C-v3KzvZ.js";import"./Dnd51l0P.js";import"./B2jTtLqC.js";import"./DvDH6DOc.js";const M={class:"container mx-auto font-mono text-white"},G={class:"grid grid-cols-4 gap-4"},H={class:"col-span-4 lg:col-span-3"},I={class:"grid grid-cols-10 gap-y-4 lg:gap-y-6"},J={class:"col-span-10 lg:col-span-2"},K={class:"col-span-10 lg:col-span-8"},O={class:"flex-col space-y-2"},P={class:"col-span-4 border-l border-gray-700 pl-4 lg:col-span-1"},Q={class:"my-2 space-y-2"},U=["onClick"],W={key:0,class:"my-2 space-y-2"},X=["onClick"],ce={__name:"index",async setup(Y){let c,x;const u=A(),a=g([]);u.query.category&&(a.value=[u.query.category]);const n=g([]);u.query.tag&&(n.value=[u.query.tag]);const k=g(!0),{data:_}=([c,x]=R(()=>z("articles",()=>E().only(["_id","_path","title","description","date","img","author","tags","categories","img","excerpt","summary"]).sort({date:-1}).find())),c=await c,x(),c),w=m(()=>[...new Set(_.value.map(e=>e.categories).flat().sort())]),b=m(()=>[...new Set(_.value.map(e=>e.tags).flat().sort())]),q=m(()=>_.value.filter(e=>!(a.value.length>0&&!a.value.every(s=>e.categories.includes(s))||n.value.length>0&&!n.value.every(s=>e.tags.includes(s)))));function N(e){n.value.includes(e)?n.value=n.value.filter(s=>s!==e):n.value.push(e)}function T(e){a.value.includes(e)?a.value=a.value.filter(s=>s!==e):a.value.push(e)}return(e,s)=>{const B=F,V=L,$=j;return l(),r("section",M,[s[2]||(s[2]=o("h1",{class:"my-6 text-2xl font-extrabold"},"Blog",-1)),o("div",G,[o("div",H,[o("div",I,[(l(!0),r(d,null,v(i(q),t=>(l(),r(d,{key:t._id},[o("div",J,p(t.date),1),o("div",K,[o("div",O,[f(B,{class:"text-orange-500",to:t._path},{default:h(()=>[D(p(t.title),1)]),_:2},1032,["to"]),f($,{value:t},{default:h(()=>[f(V,{class:"line-clamp-5 text-xs text-gray-400",value:{body:t.excerpt}},null,8,["value"])]),_:2},1032,["value"])])])],64))),128))])]),o("div",P,[o("div",Q,[s[0]||(s[0]=o("p",{class:"text-xl font-bold"},"Categories",-1)),(l(!0),r(d,null,v(i(w),t=>(l(),r("div",{key:t,class:C([{"bg-orange-500rtext-white":i(a).includes(t)},"cursor-pointer p-1 text-sm text-gray-400 hover:bg-orange-500 hover:text-white"]),onClick:y=>T(t)},p(t),11,U))),128))]),i(k)?(l(),r("div",W,[s[1]||(s[1]=o("p",{class:"text-xl font-bold"},"Tags",-1)),(l(!0),r(d,null,v(i(b),(t,y)=>(l(),r("div",{key:y,class:C([{"bg-orange-500 text-white":i(n).includes(t)},"cursor-pointer select-none p-1 text-sm text-gray-400 hover:bg-orange-500 hover:text-white"]),onClick:Z=>N(t)},p(t),11,X))),128))])):S("",!0)])])])}}};export{ce as default}; diff --git a/_nuxt/CReNMuyo.js b/_nuxt/CReNMuyo.js deleted file mode 100644 index e4f77724..00000000 --- a/_nuxt/CReNMuyo.js +++ /dev/null @@ -1 +0,0 @@ -import{$ as u,d as c,I as r,k as d,R as l,K as h,U as m,o as g,e as p,a as i,aa as f}from"./CZZfhpmp.js";function x(t){throw u({fatal:!0,statusCode:500,statusMessage:`${t} is provided by @nuxt/image. Check your console to install it or run 'npx nuxi@latest module add @nuxt/image'`})}const S={setup:()=>x("")},w=c({__name:"ProseImg",props:{src:{type:String,default:""},alt:{type:String,default:""},width:{type:[String,Number],default:void 0},height:{type:[String,Number],default:void 0}},setup(t){const n=r().public.mdc.useNuxtImage?S:"img",e=t,o=d(()=>{var a;if((a=e.src)!=null&&a.startsWith("/")&&!e.src.startsWith("//")){const s=l(h(r().app.baseURL));if(s!=="/"&&!e.src.startsWith(s))return m(s,e.src)}return e.src});return(a,s)=>(g(),p(f(i(n)),{src:i(o),alt:t.alt,width:t.width,height:t.height},null,8,["src","alt","width","height"]))}});export{w as default}; diff --git a/_nuxt/t47rUjQB.js b/_nuxt/CS4CKjMH.js similarity index 78% rename from _nuxt/t47rUjQB.js rename to _nuxt/CS4CKjMH.js index ae3b5dff..f73006ad 100644 --- a/_nuxt/t47rUjQB.js +++ b/_nuxt/CS4CKjMH.js @@ -1 +1 @@ -import n from"./DSVbkqRh.js";import{d as c,J as l,L as u}from"./CZZfhpmp.js";import"./BT7WDeVb.js";import"./CmpoAw97.js";import"./DvDH6DOc.js";import"./B2jTtLqC.js";const p=(r,t)=>u("pre",null,JSON.stringify({message:"You should use slots with ",slot:r,data:t},null,2)),h=c({name:"ContentList",props:{path:{type:String,required:!1,default:void 0},query:{type:Object,required:!1,default:void 0}},render(r){const t=l(),{path:f,query:a}=r,m={...a||{},path:f||(a==null?void 0:a.path)||"/"};return u(n,m,{default:t!=null&&t.default?({data:e,refresh:o,isPartial:d})=>t.default({list:e,refresh:o,isPartial:d,...this.$attrs}):e=>p("default",e.data),empty:e=>t!=null&&t.empty?t.empty(e):p("default",e==null?void 0:e.data),"not-found":e=>{var o;return t!=null&&t["not-found"]?(o=t==null?void 0:t["not-found"])==null?void 0:o.call(t,e):p("not-found",e==null?void 0:e.data)}})}}),i=h;export{i as default}; +import n from"./DsRHAFuR.js";import{d as c,J as l,L as u}from"./K1dcBiIN.js";import"./C6WZwVE2.js";import"./Ce34VGij.js";import"./DvDH6DOc.js";import"./NnUIAPGH.js";const p=(r,t)=>u("pre",null,JSON.stringify({message:"You should use slots with ",slot:r,data:t},null,2)),h=c({name:"ContentList",props:{path:{type:String,required:!1,default:void 0},query:{type:Object,required:!1,default:void 0}},render(r){const t=l(),{path:f,query:a}=r,m={...a||{},path:f||(a==null?void 0:a.path)||"/"};return u(n,m,{default:t!=null&&t.default?({data:e,refresh:o,isPartial:d})=>t.default({list:e,refresh:o,isPartial:d,...this.$attrs}):e=>p("default",e.data),empty:e=>t!=null&&t.empty?t.empty(e):p("default",e==null?void 0:e.data),"not-found":e=>{var o;return t!=null&&t["not-found"]?(o=t==null?void 0:t["not-found"])==null?void 0:o.call(t,e):p("not-found",e==null?void 0:e.data)}})}}),i=h;export{i as default}; diff --git a/_nuxt/CXWT5P23.js b/_nuxt/CXWT5P23.js new file mode 100644 index 00000000..df575a65 --- /dev/null +++ b/_nuxt/CXWT5P23.js @@ -0,0 +1 @@ +import{q,v as D,x as T,o as m,c as b,b as t,d as E,j as W,y as R,i as C,a as x,F as A,r as F,t as u}from"./K1dcBiIN.js";const M={id:"waveform-canvas-container",class:"bg-green h-full w-full"},N=["width","height"],P={__name:"Waveform",props:{timeDomainBufferHistory:{type:Array},canvasWidth:{type:Number},canvasHeight:{type:Number},fillStyle:{type:String,default:"rgba(0,0,0)"},strokeStyle:{type:String,default:"rgb(255, 255, 255)"}},setup(f){const s=f;return q(()=>{const d=document.getElementById("waveformCanvas2"),e=d.getContext("2d"),n=document.getElementById("waveform-canvas-container"),i=s.canvasHeight?s.canvasHeight:n.clientHeight,o=s.canvasWidth?s.canvasWidth:n.clientWidth;d.height=i,d.width=o,e.fillRect(0,0,o,i),D(s.timeDomainBufferHistory,a=>{e.fillStyle=s.fillStyle,e.fillRect(0,0,o,i),e.lineWidth=2,e.strokeStyle=s.strokeStyle,e.beginPath();const h=a.slice(-1)[0],_=h.length,y=o/_;let g=0;for(let l=0;l<_;l++){const v=h[l]/128*i/2;l===0?e.moveTo(g,v):e.lineTo(g,v),g+=y}e.lineTo(d.width,d.height/2),e.stroke()})}),T(()=>{}),(d,e)=>(m(),b("div",M,[t("canvas",{id:"waveformCanvas2",width:f.canvasWidth,height:f.canvasHeight},null,8,N)]))}},U={id:"spectrogram-canvas-container",class:"h-full w-full"},O=["width","height"],k=36,G={__name:"Spectrogram",props:{frequencyDomainBufferHistory:{type:Array},canvasWidth:{type:Number},canvasHeight:{type:Number},fillStyle:{type:String,default:"rgba(0,0,0)"}},setup(f){const s=f,d=(e,n,i,o,a)=>(e-n)*(a-n)/(i-n)+o;return q(()=>{const e=document.getElementById("spectrogramCanvas"),n=e.getContext("2d"),i=document.getElementById("spectrogram-canvas-container"),o=s.canvasHeight?s.canvasHeight:i.clientHeight,a=s.canvasWidth?s.canvasWidth:i.clientWidth;e.height=o,e.width=a,n.fillRect(0,0,a,o),D(s.frequencyDomainBufferHistory,h=>{n.fillStyle=s.fillStyle,n.fillRect(0,0,a,o);const _=h.slice(-k),y=a/128,g=o/k;for(let l=0;l<128;l++)for(let c=0;c(m(),b("div",null,[t("div",U,[t("canvas",{id:"spectrogramCanvas",width:f.canvasWidth,height:f.canvasHeight},null,8,O)])]))}},L={id:"bar-graph-container",class:"h-full w-full"},V=["width","height"],I=2,Y={__name:"FrequencyBarGraph",props:{audioBufferHistory:{type:Array},canvasWidth:{type:Number},canvasHeight:{type:Number},fillStyle:{type:String,default:"rgba(0,0,0)"},strokeStyle:{type:String,default:"rgb(255, 255, 255)"}},setup(f){const s=f,d=(e,n,i,o,a)=>(e-n)*(a-n)/(i-n)+o;return q(()=>{const e=document.getElementById("frequencyBarGraphCanvas"),n=e.getContext("2d"),i=document.getElementById("bar-graph-container"),o=s.canvasHeight?s.canvasHeight:i.clientHeight,a=s.canvasWidth?s.canvasWidth:i.clientWidth;e.height=o,e.width=a,n.fillRect(0,0,a,o),D(s.audioBufferHistory,h=>{n.fillStyle=s.fillStyle,n.fillRect(0,0,a,o);const _=h.slice(-1)[0],y=a/_.length-I;let g=0;for(let l=0;l<_.length;l++){const c=_[l],v=d(c,0,255,0,o);n.fillStyle=`rgb(${c},0,${c})`,n.fillRect(g,o-v,y,v),g+=y+I}})}),(e,n)=>(m(),b("div",null,[t("div",L,[t("canvas",{id:"frequencyBarGraphCanvas",width:f.canvasWidth,height:f.canvasHeight},null,8,V)])]))}},j={class:"container mx-auto font-mono"},z={class:"bg-background text-white"},K={class:"grid grid-cols-3 gap-4"},X={class:"col-span-3 rounded-xl bg-black/75 p-4 lg:col-span-1"},Z=t("div",{class:"mb-2 text-xl font-bold"},"Time Domain Waveform",-1),J={class:"col-span-3 rounded-xl bg-black/75 p-4 lg:col-span-1"},Q=t("div",{class:"mb-2 text-xl font-bold"},"Frequency Spectrogram",-1),tt={class:"col-span-3 rounded-xl bg-black/75 p-4 lg:col-span-1"},et=t("div",{class:"mb-2 text-xl font-bold"},"Frequency Bar Chart",-1),nt={class:"col-span-3 rounded-xl bg-black/75 p-4"},st=t("div",{class:"mb-2 text-xl font-bold"},"Frequency Buffer History",-1),ot={class:"w-full table-fixed"},at=t("thead",{class:"collapse border-b-2 md:visible"},[t("tr",null,[t("th",{class:"text-left"},"Index"),t("th",{class:"text-left"},"Mean"),t("th",{class:"text-left"},"Min"),t("th",{class:"text-left"},"Max"),t("th",{class:"text-left"},"FFT"),t("th",{class:"text-right"},"Buffer")])],-1),lt={class:"text-left font-bold"},it={class:"text-left"},ct={class:"text-left"},rt={class:"text-left"},dt={class:"text-left"},ht={class:"truncate text-right"},ut={class:"col-span-3 rounded-xl bg-black/75 p-4"},ft=t("div",{class:"mb-2 text-xl font-bold"},"Time Domain Buffer History",-1),gt={class:"w-full table-fixed"},_t=t("thead",{class:"collapse border-b-2 md:visible"},[t("tr",null,[t("th",{class:"text-left"},"Index"),t("th",{class:"text-left"},"Mean"),t("th",{class:"text-left"},"Min"),t("th",{class:"text-left"},"Max"),t("th",{class:"text-left"},"FFT"),t("th",{class:"text-right"},"Buffer")])],-1),vt={class:"text-left font-bold"},yt={class:"text-left"},mt={class:"text-left"},bt={class:"text-left"},pt={class:"text-left"},xt={class:"truncate text-right"},B=256,wt=E({__name:"index",setup(f){let s=null,d=null,e=null,n=null,i=null,o=W([]),a=null,h=W([]);W(!1);const _=()=>{requestAnimationFrame(_),e.getByteTimeDomainData(i),i!==null&&(o.value.push(i.slice()),o.value.length>B&&o.value.shift()),e.getByteFrequencyData(a),a!==null&&(h.value.push(a.slice()),h.value.length>B&&h.value.shift())},y=()=>{navigator.mediaDevices.getUserMedia({audio:!0}).then(l=>{s=l,d=new(window.AudioContext||window.webkitAudioContext),e=d.createAnalyser(),n=d.createMediaStreamSource(s),n.connect(e),e.fftSize=2048,i=new Uint8Array(e.frequencyBinCount),a=new Uint8Array(e.frequencyBinCount);for(let c=0;c{s!==null&&s.active&&s.getAudioTracks().forEach(l=>{l.stop()})};return R(()=>{console.log("disabling"),g()}),(l,c)=>{const v=P,w=G,$=Y;return m(),b("div",j,[t("div",z,[t("div",K,[t("div",{class:"col-span-3 space-x-2"},[t("div",{class:"inline-block rounded-lg bg-black px-6 py-2 text-sm font-bold uppercase text-white shadow-lg shadow-green-400/25 transition duration-150 ease-in-out hover:cursor-pointer hover:shadow-white/25",onClick:y}," Enable "),t("div",{class:"inline-block rounded-lg bg-black px-6 py-2 text-sm font-bold uppercase text-white shadow-lg shadow-red-400/25 transition duration-150 ease-in-out hover:cursor-pointer hover:shadow-white/25",onClick:g}," Disable ")]),t("div",X,[Z,C(v,{timeDomainBufferHistory:x(o),strokeStyle:"rgb(255, 0, 255)",class:"h-72 border-2 border-gray-400"},null,8,["timeDomainBufferHistory"])]),t("div",J,[Q,C(w,{frequencyDomainBufferHistory:x(h),class:"h-72 border-2 border-gray-400"},null,8,["frequencyDomainBufferHistory"])]),t("div",tt,[et,C($,{audioBufferHistory:x(h),class:"h-72 border-2 border-gray-400"},null,8,["audioBufferHistory"])]),t("div",nt,[st,t("div",null,[t("table",ot,[at,t("tbody",null,[(m(!0),b(A,null,F(x(h).slice(-10),(r,p)=>(m(),b("tr",{key:p},[t("td",lt,u(p),1),t("td",it,u((r.reduce((H,S)=>H+S)/r.length).toFixed(2)),1),t("td",ct,u(Math.min(...r)),1),t("td",rt,u(Math.max(...r)),1),t("td",dt,u(r.length),1),t("td",ht,u(r.slice(0,4))+" ... "+u(r.slice(-4)),1)]))),128))])])])]),t("div",ut,[ft,t("div",null,[t("table",gt,[_t,t("tbody",null,[(m(!0),b(A,null,F(x(o).slice(-10),(r,p)=>(m(),b("tr",{key:p},[t("td",vt,u(p),1),t("td",yt,u((r.reduce((H,S)=>H+S)/r.length).toFixed(2)),1),t("td",mt,u(Math.min(...r)),1),t("td",bt,u(Math.max(...r)),1),t("td",pt,u(r.length),1),t("td",xt,u(r.slice(0,4))+" ... "+u(r.slice(-4)),1)]))),128))])])])])])])])}}});export{wt as default}; diff --git a/_nuxt/CYevVL6b.js b/_nuxt/CYevVL6b.js new file mode 100644 index 00000000..dd28ec48 --- /dev/null +++ b/_nuxt/CYevVL6b.js @@ -0,0 +1 @@ +import{m as c,j as l,c as d,i as o,f as n,b as e,t as f,S as m,o as p,s as u}from"./K1dcBiIN.js";const h={setup(){return{show:l(!1)}}},y={class:"bg-gradeint-to-r flex min-h-screen items-center justify-center from-blue-400 to-indigo-500"},g={class:"flex w-96 items-center space-x-4 rounded-2xl bg-white p-4 shadow-xl"},_=e("h1",{class:"font-medium text-gray-900"},"Floofy McFloof",-1),x=e("p",{class:"mt-0.5 text-gray-500"}," Hey! I'm McFloof and I have been a very good boi this year. ",-1),v={class:"absolute inset-x-0 top-0 my-4 flex w-full items-center justify-center"};function w(r,s,b,t,H,S){const a=u,i=m;return p(),d("div",y,[o(i,{as:"template",show:t.show,enter:"transition transform duration-300 ease-out","enter-from":"translate-x-4 opacity-0","enter-to":"translate-x-0 opacity-100",leave:"transition transform duration-300 ease-in","leave-from":"opacity-100","leave-to":"opacity-0"},{default:n(()=>[e("div",g,[o(a,{as:"img",enter:"transition transform duration-300 ease-out","enter-from":"rotate-90 scale-50 opacity-0","enter-to":"rotate-0 scale-100 opacity-100",leave:"transition transform duration-300 ease-in","leave-from":"opacity-100","leave-to":"opacity-0",class:"h-16 w-16 rounded-full ring ring-indigo-500 ring-opacity-50 ring-offset-2",src:"/images/placeholder.png"}),o(a,{enter:"transition transform duration-300 ease-out","enter-from":"translate-x-12 opacity-0","enter-to":"translate-x-0 opacity-100",leave:"transition transform duration-300 ease-in","leave-from":"opacity-100","leave-to":"opacity-0"},{default:n(()=>[_,x]),_:1})])]),_:1},8,["show"]),e("div",v,[e("button",{class:"rounded-lg bg-blue-200 px-4 py-1.5 text-sm font-medium text-indigo-900 hover:bg-blue-100 focus:outline-none focus:ring-2 focus:ring-indigo-600",onClick:s[0]||(s[0]=j=>t.show=!t.show)},f(t.show?"Hide":"Show")+" profile ",1)])])}const B=c(h,[["render",w]]);export{B as default}; diff --git a/_nuxt/CZZfhpmp.js b/_nuxt/CZZfhpmp.js deleted file mode 100644 index 4be825c5..00000000 --- a/_nuxt/CZZfhpmp.js +++ /dev/null @@ -1,1658 +0,0 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./DV8CRu_y.js","./CuOPeUWs.js","./C-v3KzvZ.js","./Dnd51l0P.js","./B2jTtLqC.js","./DvDH6DOc.js","./B1tmNyhF.js","./BT7WDeVb.js","./CmpoAw97.js","./_...J8jiN4NX.css","./CMGdJvMz.js","./D2yfouAe.js","./BNTwU45X.js","./DS2wgvBY.js","./DKixc0ER.js","./Xli_fklN.js","./DSVbkqRh.js","./t47rUjQB.js","./CeHLcfh0.js","./B16Ch1Rg.js","./3aFKPIgF.js","./nVRvli7B.js","./Dab_E90i.js","./CZYXMW8W.js","./ProseCode.CchFRBtv.css","./DwoF_sus.js"])))=>i.map(i=>d[i]); -/** -* @vue/shared v3.5.4 -* (c) 2018-present Yuxi (Evan) You and Vue contributors -* @license MIT -**//*! #__NO_SIDE_EFFECTS__ */function nl(r){const i=Object.create(null);for(const w of r.split(","))i[w]=1;return w=>w in i}const Mt={},_o=[],dn=()=>{},ip=()=>!1,fs=r=>r.charCodeAt(0)===111&&r.charCodeAt(1)===110&&(r.charCodeAt(2)>122||r.charCodeAt(2)<97),ol=r=>r.startsWith("onUpdate:"),Qt=Object.assign,sl=(r,i)=>{const w=r.indexOf(i);w>-1&&r.splice(w,1)},ap=Object.prototype.hasOwnProperty,_t=(r,i)=>ap.call(r,i),st=Array.isArray,wo=r=>hs(r)==="[object Map]",od=r=>hs(r)==="[object Set]",lp=r=>hs(r)==="[object RegExp]",at=r=>typeof r=="function",Ut=r=>typeof r=="string",Hn=r=>typeof r=="symbol",At=r=>r!==null&&typeof r=="object",il=r=>(At(r)||at(r))&&at(r.then)&&at(r.catch),sd=Object.prototype.toString,hs=r=>sd.call(r),up=r=>hs(r).slice(8,-1),id=r=>hs(r)==="[object Object]",al=r=>Ut(r)&&r!=="NaN"&&r[0]!=="-"&&""+parseInt(r,10)===r,xo=nl(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),pi=r=>{const i=Object.create(null);return w=>i[w]||(i[w]=r(w))},cp=/-(\w)/g,tn=pi(r=>r.replace(cp,(i,w)=>w?w.toUpperCase():"")),dp=/\B([A-Z])/g,io=pi(r=>r.replace(dp,"-$1").toLowerCase()),mi=pi(r=>r.charAt(0).toUpperCase()+r.slice(1)),Vi=pi(r=>r?`on${mi(r)}`:""),Gn=(r,i)=>!Object.is(r,i),jo=(r,...i)=>{for(let w=0;w{Object.defineProperty(r,i,{configurable:!0,enumerable:!1,writable:t,value:w})},ba=r=>{const i=parseFloat(r);return isNaN(i)?r:i},ld=r=>{const i=Ut(r)?Number(r):NaN;return isNaN(i)?r:i};let ku;const ud=()=>ku||(ku=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function ll(r){if(st(r)){const i={};for(let w=0;w{if(w){const t=w.split(hp);t.length>1&&(i[t[0].trim()]=t[1].trim())}}),i}function Jn(r){let i="";if(Ut(r))i=r;else if(st(r))for(let w=0;w!!(r&&r.__v_isRef===!0),vp=r=>Ut(r)?r:r==null?"":st(r)||At(r)&&(r.toString===sd||!at(r.toString))?dd(r)?vp(r.value):JSON.stringify(r,fd,2):String(r),fd=(r,i)=>dd(i)?fd(r,i.value):wo(i)?{[`Map(${i.size})`]:[...i.entries()].reduce((w,[t,x],v)=>(w[Hi(t,v)+" =>"]=x,w),{})}:od(i)?{[`Set(${i.size})`]:[...i.values()].map(w=>Hi(w))}:Hn(i)?Hi(i):At(i)&&!st(i)&&!id(i)?String(i):i,Hi=(r,i="")=>{var w;return Hn(r)?`Symbol(${(w=r.description)!=null?w:i})`:r};/** -* @vue/reactivity v3.5.4 -* (c) 2018-present Yuxi (Evan) You and Vue contributors -* @license MIT -**/let _r;class hd{constructor(i=!1){this.detached=i,this._active=!0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.parent=_r,!i&&_r&&(this.index=(_r.scopes||(_r.scopes=[])).push(this)-1)}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let i,w;if(this.scopes)for(i=0,w=this.scopes.length;i0)return;let r;for(;Xo;){let i=Xo;for(Xo=void 0;i;){const w=i.nextEffect;if(i.nextEffect=void 0,i.flags&=-9,i.flags&1)try{i.trigger()}catch(t){r||(r=t)}i=w}}if(r)throw r}function yd(r){for(let i=r.deps;i;i=i.nextDep)i.version=-1,i.prevActiveLink=i.dep.activeLink,i.dep.activeLink=i}function gd(r){let i,w=r.depsTail;for(let t=w;t;t=t.prevDep)t.version===-1?(t===w&&(w=t.prevDep),dl(t),wp(t)):i=t,t.dep.activeLink=t.prevActiveLink,t.prevActiveLink=void 0;r.deps=i,r.depsTail=w}function _a(r){for(let i=r.deps;i;i=i.nextDep)if(i.dep.version!==i.version||i.dep.computed&&vd(i.dep.computed)||i.dep.version!==i.version)return!0;return!!r._dirty}function vd(r){if(r.flags&4&&!(r.flags&16)||(r.flags&=-17,r.globalVersion===rs))return;r.globalVersion=rs;const i=r.dep;if(r.flags|=2,i.version>0&&!r.isSSR&&!_a(r)){r.flags&=-3;return}const w=kt,t=Jr;kt=r,Jr=!0;try{yd(r);const x=r.fn(r._value);(i.version===0||Gn(x,r._value))&&(r._value=x,i.version++)}catch(x){throw i.version++,x}finally{kt=w,Jr=t,gd(r),r.flags&=-3}}function dl(r){const{dep:i,prevSub:w,nextSub:t}=r;if(w&&(w.nextSub=t,r.prevSub=void 0),t&&(t.prevSub=w,r.nextSub=void 0),i.subs===r&&(i.subs=w),!i.subs&&i.computed){i.computed.flags&=-5;for(let x=i.computed.deps;x;x=x.nextDep)dl(x)}}function wp(r){const{prevDep:i,nextDep:w}=r;i&&(i.nextDep=w,r.prevDep=void 0),w&&(w.prevDep=i,r.nextDep=void 0)}let Jr=!0;const bd=[];function zn(){bd.push(Jr),Jr=!1}function Wn(){const r=bd.pop();Jr=r===void 0?!0:r}function Mu(r){const{cleanup:i}=r;if(r.cleanup=void 0,i){const w=kt;kt=void 0;try{i()}finally{kt=w}}}let rs=0;class yi{constructor(i){this.computed=i,this.version=0,this.activeLink=void 0,this.subs=void 0}track(i){if(!kt||!Jr||kt===this.computed)return;let w=this.activeLink;if(w===void 0||w.sub!==kt)w=this.activeLink={dep:this,sub:kt,version:this.version,nextDep:void 0,prevDep:void 0,nextSub:void 0,prevSub:void 0,prevActiveLink:void 0},kt.deps?(w.prevDep=kt.depsTail,kt.depsTail.nextDep=w,kt.depsTail=w):kt.deps=kt.depsTail=w,kt.flags&4&&_d(w);else if(w.version===-1&&(w.version=this.version,w.nextDep)){const t=w.nextDep;t.prevDep=w.prevDep,w.prevDep&&(w.prevDep.nextDep=t),w.prevDep=kt.depsTail,w.nextDep=void 0,kt.depsTail.nextDep=w,kt.depsTail=w,kt.deps===w&&(kt.deps=t)}return w}trigger(i){this.version++,rs++,this.notify(i)}notify(i){ul();try{for(let w=this.subs;w;w=w.prevSub)w.sub.notify()}finally{cl()}}}function _d(r){const i=r.dep.computed;if(i&&!r.dep.subs){i.flags|=20;for(let t=i.deps;t;t=t.nextDep)_d(t)}const w=r.dep.subs;w!==r&&(r.prevSub=w,w&&(w.nextSub=r)),r.dep.subs=r}const Zs=new WeakMap,eo=Symbol(""),wa=Symbol(""),ns=Symbol("");function yr(r,i,w){if(Jr&&kt){let t=Zs.get(r);t||Zs.set(r,t=new Map);let x=t.get(w);x||t.set(w,x=new yi),x.track()}}function wn(r,i,w,t,x,v){const s=Zs.get(r);if(!s){rs++;return}const u=o=>{o&&o.trigger()};if(ul(),i==="clear")s.forEach(u);else{const o=st(r),f=o&&al(w);if(o&&w==="length"){const g=Number(t);s.forEach((m,n)=>{(n==="length"||n===ns||!Hn(n)&&n>=g)&&u(m)})}else switch(w!==void 0&&u(s.get(w)),f&&u(s.get(ns)),i){case"add":o?f&&u(s.get("length")):(u(s.get(eo)),wo(r)&&u(s.get(wa)));break;case"delete":o||(u(s.get(eo)),wo(r)&&u(s.get(wa)));break;case"set":wo(r)&&u(s.get(eo));break}}cl()}function xp(r,i){var w;return(w=Zs.get(r))==null?void 0:w.get(i)}function ho(r){const i=vt(r);return i===r?i:(yr(i,"iterate",ns),Wr(r)?i:i.map(pr))}function gi(r){return yr(r=vt(r),"iterate",ns),r}const jp={__proto__:null,[Symbol.iterator](){return Wi(this,Symbol.iterator,pr)},concat(...r){return ho(this).concat(...r.map(i=>st(i)?ho(i):i))},entries(){return Wi(this,"entries",r=>(r[1]=pr(r[1]),r))},every(r,i){return yn(this,"every",r,i,void 0,arguments)},filter(r,i){return yn(this,"filter",r,i,w=>w.map(pr),arguments)},find(r,i){return yn(this,"find",r,i,pr,arguments)},findIndex(r,i){return yn(this,"findIndex",r,i,void 0,arguments)},findLast(r,i){return yn(this,"findLast",r,i,pr,arguments)},findLastIndex(r,i){return yn(this,"findLastIndex",r,i,void 0,arguments)},forEach(r,i){return yn(this,"forEach",r,i,void 0,arguments)},includes(...r){return qi(this,"includes",r)},indexOf(...r){return qi(this,"indexOf",r)},join(r){return ho(this).join(r)},lastIndexOf(...r){return qi(this,"lastIndexOf",r)},map(r,i){return yn(this,"map",r,i,void 0,arguments)},pop(){return Vo(this,"pop")},push(...r){return Vo(this,"push",r)},reduce(r,...i){return Cu(this,"reduce",r,i)},reduceRight(r,...i){return Cu(this,"reduceRight",r,i)},shift(){return Vo(this,"shift")},some(r,i){return yn(this,"some",r,i,void 0,arguments)},splice(...r){return Vo(this,"splice",r)},toReversed(){return ho(this).toReversed()},toSorted(r){return ho(this).toSorted(r)},toSpliced(...r){return ho(this).toSpliced(...r)},unshift(...r){return Vo(this,"unshift",r)},values(){return Wi(this,"values",pr)}};function Wi(r,i,w){const t=gi(r),x=t[i]();return t!==r&&!Wr(r)&&(x._next=x.next,x.next=()=>{const v=x._next();return v.value&&(v.value=w(v.value)),v}),x}const Sp=Array.prototype;function yn(r,i,w,t,x,v){const s=gi(r),u=s!==r&&!Wr(r),o=s[i];if(o!==Sp[i]){const m=o.apply(r,v);return u?pr(m):m}let f=w;s!==r&&(u?f=function(m,n){return w.call(this,pr(m),n,r)}:w.length>2&&(f=function(m,n){return w.call(this,m,n,r)}));const g=o.call(s,f,t);return u&&x?x(g):g}function Cu(r,i,w,t){const x=gi(r);let v=w;return x!==r&&(Wr(r)?w.length>3&&(v=function(s,u,o){return w.call(this,s,u,o,r)}):v=function(s,u,o){return w.call(this,s,pr(u),o,r)}),x[i](v,...t)}function qi(r,i,w){const t=vt(r);yr(t,"iterate",ns);const x=t[i](...w);return(x===-1||x===!1)&&ml(w[0])?(w[0]=vt(w[0]),t[i](...w)):x}function Vo(r,i,w=[]){zn(),ul();const t=vt(r)[i].apply(r,w);return cl(),Wn(),t}const Ep=nl("__proto__,__v_isRef,__isVue"),wd=new Set(Object.getOwnPropertyNames(Symbol).filter(r=>r!=="arguments"&&r!=="caller").map(r=>Symbol[r]).filter(Hn));function Tp(r){Hn(r)||(r=String(r));const i=vt(this);return yr(i,"has",r),i.hasOwnProperty(r)}class xd{constructor(i=!1,w=!1){this._isReadonly=i,this._isShallow=w}get(i,w,t){const x=this._isReadonly,v=this._isShallow;if(w==="__v_isReactive")return!x;if(w==="__v_isReadonly")return x;if(w==="__v_isShallow")return v;if(w==="__v_raw")return t===(x?v?Up:Td:v?Ed:Sd).get(i)||Object.getPrototypeOf(i)===Object.getPrototypeOf(t)?i:void 0;const s=st(i);if(!x){let o;if(s&&(o=jp[w]))return o;if(w==="hasOwnProperty")return Tp}const u=Reflect.get(i,w,nr(i)?i:t);return(Hn(w)?wd.has(w):Ep(w))||(x||yr(i,"get",w),v)?u:nr(u)?s&&al(w)?u:u.value:At(u)?x?kd(u):qn(u):u}}class jd extends xd{constructor(i=!1){super(!1,i)}set(i,w,t,x){let v=i[w];if(!this._isShallow){const o=Vn(v);if(!Wr(t)&&!Vn(t)&&(v=vt(v),t=vt(t)),!st(i)&&nr(v)&&!nr(t))return o?!1:(v.value=t,!0)}const s=st(i)&&al(w)?Number(w)r,vi=r=>Reflect.getPrototypeOf(r);function Cs(r,i,w=!1,t=!1){r=r.__v_raw;const x=vt(r),v=vt(i);w||(Gn(i,v)&&yr(x,"get",i),yr(x,"get",v));const{has:s}=vi(x),u=t?fl:w?yl:pr;if(s.call(x,i))return u(r.get(i));if(s.call(x,v))return u(r.get(v));r!==x&&r.get(i)}function Os(r,i=!1){const w=this.__v_raw,t=vt(w),x=vt(r);return i||(Gn(r,x)&&yr(t,"has",r),yr(t,"has",x)),r===x?w.has(r):w.has(r)||w.has(x)}function Ps(r,i=!1){return r=r.__v_raw,!i&&yr(vt(r),"iterate",eo),Reflect.get(r,"size",r)}function Ou(r,i=!1){!i&&!Wr(r)&&!Vn(r)&&(r=vt(r));const w=vt(this);return vi(w).has.call(w,r)||(w.add(r),wn(w,"add",r,r)),this}function Pu(r,i,w=!1){!w&&!Wr(i)&&!Vn(i)&&(i=vt(i));const t=vt(this),{has:x,get:v}=vi(t);let s=x.call(t,r);s||(r=vt(r),s=x.call(t,r));const u=v.call(t,r);return t.set(r,i),s?Gn(i,u)&&wn(t,"set",r,i):wn(t,"add",r,i),this}function Au(r){const i=vt(this),{has:w,get:t}=vi(i);let x=w.call(i,r);x||(r=vt(r),x=w.call(i,r)),t&&t.call(i,r);const v=i.delete(r);return x&&wn(i,"delete",r,void 0),v}function Ru(){const r=vt(this),i=r.size!==0,w=r.clear();return i&&wn(r,"clear",void 0,void 0),w}function As(r,i){return function(t,x){const v=this,s=v.__v_raw,u=vt(s),o=i?fl:r?yl:pr;return!r&&yr(u,"iterate",eo),s.forEach((f,g)=>t.call(x,o(f),o(g),v))}}function Rs(r,i,w){return function(...t){const x=this.__v_raw,v=vt(x),s=wo(v),u=r==="entries"||r===Symbol.iterator&&s,o=r==="keys"&&s,f=x[r](...t),g=w?fl:i?yl:pr;return!i&&yr(v,"iterate",o?wa:eo),{next(){const{value:m,done:n}=f.next();return n?{value:m,done:n}:{value:u?[g(m[0]),g(m[1])]:g(m),done:n}},[Symbol.iterator](){return this}}}}function Mn(r){return function(...i){return r==="delete"?!1:r==="clear"?void 0:this}}function Pp(){const r={get(v){return Cs(this,v)},get size(){return Ps(this)},has:Os,add:Ou,set:Pu,delete:Au,clear:Ru,forEach:As(!1,!1)},i={get(v){return Cs(this,v,!1,!0)},get size(){return Ps(this)},has:Os,add(v){return Ou.call(this,v,!0)},set(v,s){return Pu.call(this,v,s,!0)},delete:Au,clear:Ru,forEach:As(!1,!0)},w={get(v){return Cs(this,v,!0)},get size(){return Ps(this,!0)},has(v){return Os.call(this,v,!0)},add:Mn("add"),set:Mn("set"),delete:Mn("delete"),clear:Mn("clear"),forEach:As(!0,!1)},t={get(v){return Cs(this,v,!0,!0)},get size(){return Ps(this,!0)},has(v){return Os.call(this,v,!0)},add:Mn("add"),set:Mn("set"),delete:Mn("delete"),clear:Mn("clear"),forEach:As(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(v=>{r[v]=Rs(v,!1,!1),w[v]=Rs(v,!0,!1),i[v]=Rs(v,!1,!0),t[v]=Rs(v,!0,!0)}),[r,w,i,t]}const[Ap,Rp,Lp,Ip]=Pp();function hl(r,i){const w=i?r?Ip:Lp:r?Rp:Ap;return(t,x,v)=>x==="__v_isReactive"?!r:x==="__v_isReadonly"?r:x==="__v_raw"?t:Reflect.get(_t(w,x)&&x in t?w:t,x,v)}const Dp={get:hl(!1,!1)},Fp={get:hl(!1,!0)},Np={get:hl(!0,!1)};const Sd=new WeakMap,Ed=new WeakMap,Td=new WeakMap,Up=new WeakMap;function Bp(r){switch(r){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function Gp(r){return r.__v_skip||!Object.isExtensible(r)?0:Bp(up(r))}function qn(r){return Vn(r)?r:pl(r,!1,Mp,Dp,Sd)}function ps(r){return pl(r,!1,Op,Fp,Ed)}function kd(r){return pl(r,!0,Cp,Np,Td)}function pl(r,i,w,t,x){if(!At(r)||r.__v_raw&&!(i&&r.__v_isReactive))return r;const v=x.get(r);if(v)return v;const s=Gp(r);if(s===0)return r;const u=new Proxy(r,s===2?t:w);return x.set(r,u),u}function to(r){return Vn(r)?to(r.__v_raw):!!(r&&r.__v_isReactive)}function Vn(r){return!!(r&&r.__v_isReadonly)}function Wr(r){return!!(r&&r.__v_isShallow)}function ml(r){return r?!!r.__v_raw:!1}function vt(r){const i=r&&r.__v_raw;return i?vt(i):r}function Vp(r){return!_t(r,"__v_skip")&&Object.isExtensible(r)&&ad(r,"__v_skip",!0),r}const pr=r=>At(r)?qn(r):r,yl=r=>At(r)?kd(r):r;function nr(r){return r?r.__v_isRef===!0:!1}function mt(r){return Md(r,!1)}function os(r){return Md(r,!0)}function Md(r,i){return nr(r)?r:new Hp(r,i)}class Hp{constructor(i,w){this.dep=new yi,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=w?i:vt(i),this._value=w?i:pr(i),this.__v_isShallow=w}get value(){return this.dep.track(),this._value}set value(i){const w=this._rawValue,t=this.__v_isShallow||Wr(i)||Vn(i);i=t?i:vt(i),Gn(i,w)&&(this._rawValue=i,this._value=t?i:pr(i),this.dep.trigger())}}function Vt(r){return nr(r)?r.value:r}function J_(r){return at(r)?r():Vt(r)}const zp={get:(r,i,w)=>i==="__v_raw"?r:Vt(Reflect.get(r,i,w)),set:(r,i,w,t)=>{const x=r[i];return nr(x)&&!nr(w)?(x.value=w,!0):Reflect.set(r,i,w,t)}};function Cd(r){return to(r)?r:new Proxy(r,zp)}class Wp{constructor(i){this.__v_isRef=!0,this._value=void 0;const w=this.dep=new yi,{get:t,set:x}=i(w.track.bind(w),w.trigger.bind(w));this._get=t,this._set=x}get value(){return this._value=this._get()}set value(i){this._set(i)}}function ew(r){return new Wp(r)}function tw(r){const i=st(r)?new Array(r.length):{};for(const w in r)i[w]=Od(r,w);return i}class qp{constructor(i,w,t){this._object=i,this._key=w,this._defaultValue=t,this.__v_isRef=!0,this._value=void 0}get value(){const i=this._object[this._key];return this._value=i===void 0?this._defaultValue:i}set value(i){this._object[this._key]=i}get dep(){return xp(vt(this._object),this._key)}}class Xp{constructor(i){this._getter=i,this.__v_isRef=!0,this.__v_isReadonly=!0,this._value=void 0}get value(){return this._value=this._getter()}}function Yp(r,i,w){return nr(r)?r:at(r)?new Xp(r):At(r)&&arguments.length>1?Od(r,i,w):mt(r)}function Od(r,i,w){const t=r[i];return nr(t)?t:new qp(r,i,w)}class $p{constructor(i,w,t){this.fn=i,this.setter=w,this._value=void 0,this.dep=new yi(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=rs-1,this.effect=this,this.__v_isReadonly=!w,this.isSSR=t}notify(){this.flags|=16,kt!==this&&this.dep.notify()}get value(){const i=this.dep.track();return vd(this),i&&(i.version=this.dep.version),this._value}set value(i){this.setter&&this.setter(i)}}function Zp(r,i,w=!1){let t,x;return at(r)?t=r:(t=r.get,x=r.set),new $p(t,x,w)}const Ls={},Ks=new WeakMap;let Kn;function Kp(r,i=!1,w=Kn){if(w){let t=Ks.get(w);t||Ks.set(w,t=[]),t.push(r)}}function Qp(r,i,w=Mt){const{immediate:t,deep:x,once:v,scheduler:s,augmentJob:u,call:o}=w,f=b=>x?b:Wr(b)||x===!1||x===0?bn(b,1):bn(b);let g,m,n,a,l=!1,d=!1;if(nr(r)?(m=()=>r.value,l=Wr(r)):to(r)?(m=()=>f(r),l=!0):st(r)?(d=!0,l=r.some(b=>to(b)||Wr(b)),m=()=>r.map(b=>{if(nr(b))return b.value;if(to(b))return f(b);if(at(b))return o?o(b,2):b()})):at(r)?i?m=o?()=>o(r,2):r:m=()=>{if(n){zn();try{n()}finally{Wn()}}const b=Kn;Kn=g;try{return o?o(r,3,[a]):r(a)}finally{Kn=b}}:m=dn,i&&x){const b=m,j=x===!0?1/0:x;m=()=>bn(b(),j)}const y=_p(),h=()=>{g.stop(),y&&sl(y.effects,g)};if(v)if(i){const b=i;i=(...j)=>{b(...j),h()}}else{const b=m;m=()=>{b(),h()}}let c=d?new Array(r.length).fill(Ls):Ls;const p=b=>{if(!(!(g.flags&1)||!g.dirty&&!b))if(i){const j=g.run();if(x||l||(d?j.some((M,E)=>Gn(M,c[E])):Gn(j,c))){n&&n();const M=Kn;Kn=g;try{const E=[j,c===Ls?void 0:d&&c[0]===Ls?[]:c,a];o?o(i,3,E):i(...E),c=j}finally{Kn=M}}}else g.run()};return u&&u(p),g=new pd(m),g.scheduler=s?()=>s(p,!1):p,a=b=>Kp(b,!1,g),n=g.onStop=()=>{const b=Ks.get(g);if(b){if(o)o(b,4);else for(const j of b)j();Ks.delete(g)}},i?t?p(!0):c=g.run():s?s(p.bind(null,!0),!0):g.run(),h.pause=g.pause.bind(g),h.resume=g.resume.bind(g),h.stop=h,h}function bn(r,i=1/0,w){if(i<=0||!At(r)||r.__v_skip||(w=w||new Set,w.has(r)))return r;if(w.add(r),i--,nr(r))bn(r.value,i,w);else if(st(r))for(let t=0;t{bn(t,i,w)});else if(id(r)){for(const t in r)bn(r[t],i,w);for(const t of Object.getOwnPropertySymbols(r))Object.prototype.propertyIsEnumerable.call(r,t)&&bn(r[t],i,w)}return r}/** -* @vue/runtime-core v3.5.4 -* (c) 2018-present Yuxi (Evan) You and Vue contributors -* @license MIT -**/function ms(r,i,w,t){try{return t?r(...t):r()}catch(x){Po(x,i,w)}}function rn(r,i,w,t){if(at(r)){const x=ms(r,i,w,t);return x&&il(x)&&x.catch(v=>{Po(v,i,w)}),x}if(st(r)){const x=[];for(let v=0;v>>1,x=wr[t],v=is(x);v=is(w)?wr.push(r):wr.splice(em(i),0,r),r.flags|=1,Ad()}}function Ad(){!ss&&!xa&&(xa=!0,gl=Pd.then(Rd))}function ja(r){st(r)?So.push(...r):Pn&&r.id===-1?Pn.splice(mo+1,0,r):r.flags&1||(So.push(r),r.flags|=1),Ad()}function Lu(r,i,w=ss?un+1:0){for(;wis(w)-is(t));if(So.length=0,Pn){Pn.push(...i);return}for(Pn=i,mo=0;mor.id==null?r.flags&2?-1:1/0:r.id;function Rd(r){xa=!1,ss=!0;try{for(un=0;un{t._d&&qu(-1);const v=Js(i);let s;try{s=r(...x)}finally{Js(v),t._d&&qu(1)}return s};return t._n=!0,t._c=!0,t._d=!0,t}function rw(r,i){if(Kt===null)return r;const w=xi(Kt),t=r.dirs||(r.dirs=[]);for(let x=0;xr.__isTeleport,An=Symbol("_leaveCb"),Is=Symbol("_enterCb");function rm(){const r={isMounted:!1,isLeaving:!1,isUnmounting:!1,leavingVNodes:new Map};return en(()=>{r.isMounted=!0}),gs(()=>{r.isUnmounting=!0}),r}const zr=[Function,Array],Dd={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:zr,onEnter:zr,onAfterEnter:zr,onEnterCancelled:zr,onBeforeLeave:zr,onLeave:zr,onAfterLeave:zr,onLeaveCancelled:zr,onBeforeAppear:zr,onAppear:zr,onAfterAppear:zr,onAppearCancelled:zr},Fd=r=>{const i=r.subTree;return i.component?Fd(i.component):i},nm={name:"BaseTransition",props:Dd,setup(r,{slots:i}){const w=ao(),t=rm();return()=>{const x=i.default&&Bd(i.default(),!0);if(!x||!x.length)return;const v=Nd(x),s=vt(r),{mode:u}=s;if(t.isLeaving)return Xi(v);const o=Iu(v);if(!o)return Xi(v);let f=Sa(o,s,t,w,n=>f=n);o.type!==$t&&To(o,f);const g=w.subTree,m=g&&Iu(g);if(m&&m.type!==$t&&!Qr(o,m)&&Fd(w).type!==$t){const n=Sa(m,s,t,w);if(To(m,n),u==="out-in"&&o.type!==$t)return t.isLeaving=!0,n.afterLeave=()=>{t.isLeaving=!1,w.job.flags&8||w.update(),delete n.afterLeave},Xi(v);u==="in-out"&&o.type!==$t&&(n.delayLeave=(a,l,d)=>{const y=Ud(t,m);y[String(m.key)]=m,a[An]=()=>{l(),a[An]=void 0,delete f.delayedLeave},f.delayedLeave=d})}return v}}};function Nd(r){let i=r[0];if(r.length>1){for(const w of r)if(w.type!==$t){i=w;break}}return i}const om=nm;function Ud(r,i){const{leavingVNodes:w}=r;let t=w.get(i.type);return t||(t=Object.create(null),w.set(i.type,t)),t}function Sa(r,i,w,t,x){const{appear:v,mode:s,persisted:u=!1,onBeforeEnter:o,onEnter:f,onAfterEnter:g,onEnterCancelled:m,onBeforeLeave:n,onLeave:a,onAfterLeave:l,onLeaveCancelled:d,onBeforeAppear:y,onAppear:h,onAfterAppear:c,onAppearCancelled:p}=i,b=String(r.key),j=Ud(w,r),M=(O,L)=>{O&&rn(O,t,9,L)},E=(O,L)=>{const C=L[1];M(O,L),st(O)?O.every(I=>I.length<=1)&&C():O.length<=1&&C()},k={mode:s,persisted:u,beforeEnter(O){let L=o;if(!w.isMounted)if(v)L=y||o;else return;O[An]&&O[An](!0);const C=j[b];C&&Qr(r,C)&&C.el[An]&&C.el[An](),M(L,[O])},enter(O){let L=f,C=g,I=m;if(!w.isMounted)if(v)L=h||f,C=c||g,I=p||m;else return;let A=!1;const N=O[Is]=F=>{A||(A=!0,F?M(I,[O]):M(C,[O]),k.delayedLeave&&k.delayedLeave(),O[Is]=void 0)};L?E(L,[O,N]):N()},leave(O,L){const C=String(r.key);if(O[Is]&&O[Is](!0),w.isUnmounting)return L();M(n,[O]);let I=!1;const A=O[An]=N=>{I||(I=!0,L(),N?M(d,[O]):M(l,[O]),O[An]=void 0,j[C]===r&&delete j[C])};j[C]=r,a?E(a,[O,A]):A()},clone(O){const L=Sa(O,i,w,t,x);return x&&x(L),L}};return k}function Xi(r){if(ys(r))return r=hn(r),r.children=null,r}function Iu(r){if(!ys(r))return Id(r.type)&&r.children?Nd(r.children):r;const{shapeFlag:i,children:w}=r;if(w){if(i&16)return w[0];if(i&32&&at(w.default))return w.default()}}function To(r,i){r.shapeFlag&6&&r.component?(r.transition=i,To(r.component.subTree,i)):r.shapeFlag&128?(r.ssContent.transition=i.clone(r.ssContent),r.ssFallback.transition=i.clone(r.ssFallback)):r.transition=i}function Bd(r,i=!1,w){let t=[],x=0;for(let v=0;v1)for(let v=0;vei(l,i&&(st(i)?i[d]:i),w,t,x));return}if(Un(t)&&!x)return;const v=t.shapeFlag&4?xi(t.component):t.el,s=x?null:v,{i:u,r:o}=r,f=i&&i.r,g=u.refs===Mt?u.refs={}:u.refs,m=u.setupState,n=vt(m),a=m===Mt?()=>!1:l=>_t(n,l);if(f!=null&&f!==o&&(Ut(f)?(g[f]=null,a(f)&&(m[f]=null)):nr(f)&&(f.value=null)),at(o))ms(o,u,12,[s,g]);else{const l=Ut(o),d=nr(o);if(l||d){const y=()=>{if(r.f){const h=l?a(o)?m[o]:g[o]:o.value;x?st(h)&&sl(h,v):st(h)?h.includes(v)||h.push(v):l?(g[o]=[v],a(o)&&(m[o]=g[o])):(o.value=[v],r.k&&(g[r.k]=o.value))}else l?(g[o]=s,a(o)&&(m[o]=s)):d&&(o.value=s,r.k&&(g[r.k]=s))};s?(y.id=-1,lr(y,w)):y()}}}let Du=!1;const po=()=>{Du||(console.error("Hydration completed but contains mismatches."),Du=!0)},im=r=>r.namespaceURI.includes("svg")&&r.tagName!=="foreignObject",am=r=>r.namespaceURI.includes("MathML"),Ds=r=>{if(r.nodeType===1){if(im(r))return"svg";if(am(r))return"mathml"}},vo=r=>r.nodeType===8;function lm(r){const{mt:i,p:w,o:{patchProp:t,createText:x,nextSibling:v,parentNode:s,remove:u,insert:o,createComment:f}}=r,g=(p,b)=>{if(!b.hasChildNodes()){w(null,p,b),Qs(),b._vnode=p;return}m(b.firstChild,p,null,null,null),Qs(),b._vnode=p},m=(p,b,j,M,E,k=!1)=>{k=k||!!b.dynamicChildren;const O=vo(p)&&p.data==="[",L=()=>d(p,b,j,M,E,O),{type:C,ref:I,shapeFlag:A,patchFlag:N}=b;let F=p.nodeType;b.el=p,N===-2&&(k=!1,b.dynamicChildren=null);let B=null;switch(C){case no:F!==3?b.children===""?(o(b.el=x(""),s(p),p),B=p):B=L():(p.data!==b.children&&(po(),p.data=b.children),B=v(p));break;case $t:c(p)?(B=v(p),h(b.el=p.content.firstChild,p,j)):F!==8||O?B=L():B=v(p);break;case $o:if(O&&(p=v(p),F=p.nodeType),F===1||F===3){B=p;const W=!b.children.length;for(let H=0;H{k=k||!!b.dynamicChildren;const{type:O,props:L,patchFlag:C,shapeFlag:I,dirs:A,transition:N}=b,F=O==="input"||O==="option";if(F||C!==-1){A&&cn(b,null,j,"created");let B=!1;if(c(p)){B=cf(M,N)&&j&&j.vnode.props&&j.vnode.props.appear;const H=p.content.firstChild;B&&N.beforeEnter(H),h(H,p,j),b.el=p=H}if(I&16&&!(L&&(L.innerHTML||L.textContent))){let H=a(p.firstChild,b,p,j,M,E,k);for(;H;){Fs(p,1)||po();const V=H;H=H.nextSibling,u(V)}}else I&8&&p.textContent!==b.children&&(Fs(p,0)||po(),p.textContent=b.children);if(L){if(F||!k||C&48){const H=p.tagName.includes("-");for(const V in L)(F&&(V.endsWith("value")||V==="indeterminate")||fs(V)&&!xo(V)||V[0]==="."||H)&&t(p,V,null,L[V],void 0,j)}else if(L.onClick)t(p,"onClick",null,L.onClick,void 0,j);else if(C&4&&to(L.style))for(const H in L.style)L.style[H]}let W;(W=L&&L.onVnodeBeforeMount)&&xr(W,j,b),A&&cn(b,null,j,"beforeMount"),((W=L&&L.onVnodeMounted)||A||B)&&yf(()=>{W&&xr(W,j,b),B&&N.enter(p),A&&cn(b,null,j,"mounted")},M)}return p.nextSibling},a=(p,b,j,M,E,k,O)=>{O=O||!!b.dynamicChildren;const L=b.children,C=L.length;for(let I=0;I{const{slotScopeIds:O}=b;O&&(E=E?E.concat(O):O);const L=s(p),C=a(v(p),b,L,j,M,E,k);return C&&vo(C)&&C.data==="]"?v(b.anchor=C):(po(),o(b.anchor=f("]"),L,C),C)},d=(p,b,j,M,E,k)=>{if(Fs(p.parentElement,1)||po(),b.el=null,k){const C=y(p);for(;;){const I=v(p);if(I&&I!==C)u(I);else break}}const O=v(p),L=s(p);return u(p),w(null,b,L,O,j,M,Ds(L),E),O},y=(p,b="[",j="]")=>{let M=0;for(;p;)if(p=v(p),p&&vo(p)&&(p.data===b&&M++,p.data===j)){if(M===0)return v(p);M--}return p},h=(p,b,j)=>{const M=b.parentNode;M&&M.replaceChild(p,b);let E=j;for(;E;)E.vnode.el===b&&(E.vnode.el=E.subTree.el=p),E=E.parent},c=p=>p.nodeType===1&&p.tagName.toLowerCase()==="template";return[g,m]}const Fu="data-allow-mismatch",um={0:"text",1:"children",2:"class",3:"style",4:"attribute"};function Fs(r,i){if(i===0||i===1)for(;r&&!r.hasAttribute(Fu);)r=r.parentElement;const w=r&&r.getAttribute(Fu);if(w==null)return!1;if(w==="")return!0;{const t=w.split(",");return i===0&&t.includes("children")?!0:w.split(",").includes(um[i])}}function cm(r,i){if(vo(r)&&r.data==="["){let w=1,t=r.nextSibling;for(;t;){if(t.nodeType===1)i(t);else if(vo(t))if(t.data==="]"){if(--w===0)break}else t.data==="["&&w++;t=t.nextSibling}}else i(r)}const Un=r=>!!r.type.__asyncLoader;/*! #__NO_SIDE_EFFECTS__ */function ht(r){at(r)&&(r={loader:r});const{loader:i,loadingComponent:w,errorComponent:t,delay:x=200,hydrate:v,timeout:s,suspensible:u=!0,onError:o}=r;let f=null,g,m=0;const n=()=>(m++,f=null,a()),a=()=>{let l;return f||(l=f=i().catch(d=>{if(d=d instanceof Error?d:new Error(String(d)),o)return new Promise((y,h)=>{o(d,()=>y(n()),()=>h(d),m+1)});throw d}).then(d=>l!==f&&f?f:(d&&(d.__esModule||d[Symbol.toStringTag]==="Module")&&(d=d.default),g=d,d)))};return gr({name:"AsyncComponentWrapper",__asyncLoader:a,__asyncHydrate(l,d,y){const h=v?()=>{const c=v(y,p=>cm(l,p));c&&(d.bum||(d.bum=[])).push(c)}:y;g?h():a().then(()=>!d.isUnmounted&&h())},get __asyncResolved(){return g},setup(){const l=Zt;if(vl(l),g)return()=>Yi(g,l);const d=p=>{f=null,Po(p,l,13,!t)};if(u&&l.suspense||_s)return a().then(p=>()=>Yi(p,l)).catch(p=>(d(p),()=>t?ft(t,{error:p}):null));const y=mt(!1),h=mt(),c=mt(!!x);return x&&setTimeout(()=>{c.value=!1},x),s!=null&&setTimeout(()=>{if(!y.value&&!h.value){const p=new Error(`Async component timed out after ${s}ms.`);d(p),h.value=p}},s),a().then(()=>{y.value=!0,l.parent&&ys(l.parent.vnode)&&bi(l.parent.update)}).catch(p=>{d(p),h.value=p}),()=>{if(y.value&&g)return Yi(g,l);if(h.value&&t)return ft(t,{error:h.value});if(w&&!c.value)return ft(w)}}})}function Yi(r,i){const{ref:w,props:t,children:x,ce:v}=i.vnode,s=ft(r,t,x);return s.ref=w,s.ce=v,delete i.vnode.ce,s}const ys=r=>r.type.__isKeepAlive,dm={name:"KeepAlive",__isKeepAlive:!0,props:{include:[String,RegExp,Array],exclude:[String,RegExp,Array],max:[String,Number]},setup(r,{slots:i}){const w=ao(),t=w.ctx;if(!t.renderer)return()=>{const c=i.default&&i.default();return c&&c.length===1?c[0]:c};const x=new Map,v=new Set;let s=null;const u=w.suspense,{renderer:{p:o,m:f,um:g,o:{createElement:m}}}=t,n=m("div");t.activate=(c,p,b,j,M)=>{const E=c.component;f(c,p,b,0,u),o(E.vnode,c,p,b,E,u,j,c.slotScopeIds,M),lr(()=>{E.isDeactivated=!1,E.a&&jo(E.a);const k=c.props&&c.props.onVnodeMounted;k&&xr(k,E.parent,c)},u)},t.deactivate=c=>{const p=c.component;ri(p.m),ri(p.a),f(c,n,null,1,u),lr(()=>{p.da&&jo(p.da);const b=c.props&&c.props.onVnodeUnmounted;b&&xr(b,p.parent,c),p.isDeactivated=!0},u)};function a(c){$i(c),g(c,w,u,!0)}function l(c){x.forEach((p,b)=>{const j=Ra(p.type);j&&!c(j)&&d(b)})}function d(c){const p=x.get(c);p&&(!s||!Qr(p,s))?a(p):s&&$i(s),x.delete(c),v.delete(c)}Bn(()=>[r.include,r.exclude],([c,p])=>{c&&l(b=>Wo(c,b)),p&&l(b=>!Wo(p,b))},{flush:"post",deep:!0});let y=null;const h=()=>{y!=null&&(ni(w.subTree.type)?lr(()=>{x.set(y,Ns(w.subTree))},w.subTree.suspense):x.set(y,Ns(w.subTree)))};return en(h),zd(h),gs(()=>{x.forEach(c=>{const{subTree:p,suspense:b}=w,j=Ns(p);if(c.type===j.type&&c.key===j.key){$i(j);const M=j.component.da;M&&lr(M,b);return}a(c)})}),()=>{if(y=null,!i.default)return s=null;const c=i.default(),p=c[0];if(c.length>1)return s=null,c;if(!Mo(p)||!(p.shapeFlag&4)&&!(p.shapeFlag&128))return s=null,p;let b=Ns(p);if(b.type===$t)return s=null,b;const j=b.type,M=Ra(Un(b)?b.type.__asyncResolved||{}:j),{include:E,exclude:k,max:O}=r;if(E&&(!M||!Wo(E,M))||k&&M&&Wo(k,M))return b.shapeFlag&=-257,s=b,p;const L=b.key==null?j:b.key,C=x.get(L);return b.el&&(b=hn(b),p.shapeFlag&128&&(p.ssContent=b)),y=L,C?(b.el=C.el,b.component=C.component,b.transition&&To(b,b.transition),b.shapeFlag|=512,v.delete(L),v.add(L)):(v.add(L),O&&v.size>parseInt(O,10)&&d(v.values().next().value)),b.shapeFlag|=256,s=b,ni(p.type)?p:b}}},fm=dm;function Wo(r,i){return st(r)?r.some(w=>Wo(w,i)):Ut(r)?r.split(",").includes(i):lp(r)?(r.lastIndex=0,r.test(i)):!1}function Gd(r,i){Hd(r,"a",i)}function Vd(r,i){Hd(r,"da",i)}function Hd(r,i,w=Zt){const t=r.__wdc||(r.__wdc=()=>{let x=w;for(;x;){if(x.isDeactivated)return;x=x.parent}return r()});if(_i(i,t,w),w){let x=w.parent;for(;x&&x.parent;)ys(x.parent.vnode)&&hm(t,i,w,x),x=x.parent}}function hm(r,i,w,t){const x=_i(i,r,t,!0);vs(()=>{sl(t[i],x)},w)}function $i(r){r.shapeFlag&=-257,r.shapeFlag&=-513}function Ns(r){return r.shapeFlag&128?r.ssContent:r}function _i(r,i,w=Zt,t=!1){if(w){const x=w[r]||(w[r]=[]),v=i.__weh||(i.__weh=(...s)=>{zn();const u=oo(w),o=rn(i,w,r,s);return u(),Wn(),o});return t?x.unshift(v):x.push(v),v}}const xn=r=>(i,w=Zt)=>{(!_s||r==="sp")&&_i(r,(...t)=>i(...t),w)},pm=xn("bm"),en=xn("m"),mm=xn("bu"),zd=xn("u"),gs=xn("bum"),vs=xn("um"),ym=xn("sp"),gm=xn("rtg"),vm=xn("rtc");function Wd(r,i=Zt){_i("ec",r,i)}const qd="components";function bm(r,i){return Yd(qd,r,!0,i)||r}const Xd=Symbol.for("v-ndc");function _m(r){return Ut(r)?Yd(qd,r,!1)||r:r||Xd}function Yd(r,i,w=!0,t=!1){const x=Kt||Zt;if(x){const v=x.type;{const u=Ra(v,!1);if(u&&(u===i||u===tn(i)||u===mi(tn(i))))return v}const s=Nu(x[r]||v[r],i)||Nu(x.appContext[r],i);return!s&&t?v:s}}function Nu(r,i){return r&&(r[i]||r[tn(i)]||r[mi(tn(i))])}function nw(r,i,w,t){let x;const v=w,s=st(r);if(s||Ut(r)){const u=s&&to(r);let o=!1;u&&(o=!Wr(r),r=gi(r)),x=new Array(r.length);for(let f=0,g=r.length;fi(u,o,void 0,v));else{const u=Object.keys(r);x=new Array(u.length);for(let o=0,f=u.length;oMo(i)?!(i.type===$t||i.type===mr&&!$d(i.children)):!0)?r:null}const Ea=r=>r?wf(r)?xi(r):Ea(r.parent):null,Yo=Qt(Object.create(null),{$:r=>r,$el:r=>r.vnode.el,$data:r=>r.data,$props:r=>r.props,$attrs:r=>r.attrs,$slots:r=>r.slots,$refs:r=>r.refs,$parent:r=>Ea(r.parent),$root:r=>Ea(r.root),$host:r=>r.ce,$emit:r=>r.emit,$options:r=>bl(r),$forceUpdate:r=>r.f||(r.f=()=>{bi(r.update)}),$nextTick:r=>r.n||(r.n=Hr.bind(r.proxy)),$watch:r=>Gm.bind(r)}),Zi=(r,i)=>r!==Mt&&!r.__isScriptSetup&&_t(r,i),wm={get({_:r},i){if(i==="__v_skip")return!0;const{ctx:w,setupState:t,data:x,props:v,accessCache:s,type:u,appContext:o}=r;let f;if(i[0]!=="$"){const a=s[i];if(a!==void 0)switch(a){case 1:return t[i];case 2:return x[i];case 4:return w[i];case 3:return v[i]}else{if(Zi(t,i))return s[i]=1,t[i];if(x!==Mt&&_t(x,i))return s[i]=2,x[i];if((f=r.propsOptions[0])&&_t(f,i))return s[i]=3,v[i];if(w!==Mt&&_t(w,i))return s[i]=4,w[i];Ta&&(s[i]=0)}}const g=Yo[i];let m,n;if(g)return i==="$attrs"&&yr(r.attrs,"get",""),g(r);if((m=u.__cssModules)&&(m=m[i]))return m;if(w!==Mt&&_t(w,i))return s[i]=4,w[i];if(n=o.config.globalProperties,_t(n,i))return n[i]},set({_:r},i,w){const{data:t,setupState:x,ctx:v}=r;return Zi(x,i)?(x[i]=w,!0):t!==Mt&&_t(t,i)?(t[i]=w,!0):_t(r.props,i)||i[0]==="$"&&i.slice(1)in r?!1:(v[i]=w,!0)},has({_:{data:r,setupState:i,accessCache:w,ctx:t,appContext:x,propsOptions:v}},s){let u;return!!w[s]||r!==Mt&&_t(r,s)||Zi(i,s)||(u=v[0])&&_t(u,s)||_t(t,s)||_t(Yo,s)||_t(x.config.globalProperties,s)},defineProperty(r,i,w){return w.get!=null?r._.accessCache[i]=0:_t(w,"value")&&this.set(r,i,w.value,null),Reflect.defineProperty(r,i,w)}};function sw(){return xm().slots}function xm(){const r=ao();return r.setupContext||(r.setupContext=jf(r))}function Uu(r){return st(r)?r.reduce((i,w)=>(i[w]=null,i),{}):r}function iw(r){const i=ao();let w=r();return Pa(),il(w)&&(w=w.catch(t=>{throw oo(i),t})),[w,()=>oo(i)]}let Ta=!0;function jm(r){const i=bl(r),w=r.proxy,t=r.ctx;Ta=!1,i.beforeCreate&&Bu(i.beforeCreate,r,"bc");const{data:x,computed:v,methods:s,watch:u,provide:o,inject:f,created:g,beforeMount:m,mounted:n,beforeUpdate:a,updated:l,activated:d,deactivated:y,beforeDestroy:h,beforeUnmount:c,destroyed:p,unmounted:b,render:j,renderTracked:M,renderTriggered:E,errorCaptured:k,serverPrefetch:O,expose:L,inheritAttrs:C,components:I,directives:A,filters:N}=i;if(f&&Sm(f,t,null),s)for(const W in s){const H=s[W];at(H)&&(t[W]=H.bind(w))}if(x){const W=x.call(w,w);At(W)&&(r.data=qn(W))}if(Ta=!0,v)for(const W in v){const H=v[W],V=at(H)?H.bind(w,w):at(H.get)?H.get.bind(w,w):dn,K=!at(H)&&at(H.set)?H.set.bind(w):dn,J=jt({get:V,set:K});Object.defineProperty(t,W,{enumerable:!0,configurable:!0,get:()=>J.value,set:le=>J.value=le})}if(u)for(const W in u)Zd(u[W],t,w,W);if(o){const W=at(o)?o.call(w):o;Reflect.ownKeys(W).forEach(H=>{qr(H,W[H])})}g&&Bu(g,r,"c");function B(W,H){st(H)?H.forEach(V=>W(V.bind(w))):H&&W(H.bind(w))}if(B(pm,m),B(en,n),B(mm,a),B(zd,l),B(Gd,d),B(Vd,y),B(Wd,k),B(vm,M),B(gm,E),B(gs,c),B(vs,b),B(ym,O),st(L))if(L.length){const W=r.exposed||(r.exposed={});L.forEach(H=>{Object.defineProperty(W,H,{get:()=>w[H],set:V=>w[H]=V})})}else r.exposed||(r.exposed={});j&&r.render===dn&&(r.render=j),C!=null&&(r.inheritAttrs=C),I&&(r.components=I),A&&(r.directives=A),O&&vl(r)}function Sm(r,i,w=dn){st(r)&&(r=ka(r));for(const t in r){const x=r[t];let v;At(x)?"default"in x?v=zt(x.from||t,x.default,!0):v=zt(x.from||t):v=zt(x),nr(v)?Object.defineProperty(i,t,{enumerable:!0,configurable:!0,get:()=>v.value,set:s=>v.value=s}):i[t]=v}}function Bu(r,i,w){rn(st(r)?r.map(t=>t.bind(i.proxy)):r.bind(i.proxy),i,w)}function Zd(r,i,w,t){let x=t.includes(".")?hf(w,t):()=>w[t];if(Ut(r)){const v=i[r];at(v)&&Bn(x,v)}else if(at(r))Bn(x,r.bind(w));else if(At(r))if(st(r))r.forEach(v=>Zd(v,i,w,t));else{const v=at(r.handler)?r.handler.bind(w):i[r.handler];at(v)&&Bn(x,v,r)}}function bl(r){const i=r.type,{mixins:w,extends:t}=i,{mixins:x,optionsCache:v,config:{optionMergeStrategies:s}}=r.appContext,u=v.get(i);let o;return u?o=u:!x.length&&!w&&!t?o=i:(o={},x.length&&x.forEach(f=>ti(o,f,s,!0)),ti(o,i,s)),At(i)&&v.set(i,o),o}function ti(r,i,w,t=!1){const{mixins:x,extends:v}=i;v&&ti(r,v,w,!0),x&&x.forEach(s=>ti(r,s,w,!0));for(const s in i)if(!(t&&s==="expose")){const u=Em[s]||w&&w[s];r[s]=u?u(r[s],i[s]):i[s]}return r}const Em={data:Gu,props:Vu,emits:Vu,methods:qo,computed:qo,beforeCreate:br,created:br,beforeMount:br,mounted:br,beforeUpdate:br,updated:br,beforeDestroy:br,beforeUnmount:br,destroyed:br,unmounted:br,activated:br,deactivated:br,errorCaptured:br,serverPrefetch:br,components:qo,directives:qo,watch:km,provide:Gu,inject:Tm};function Gu(r,i){return i?r?function(){return Qt(at(r)?r.call(this,this):r,at(i)?i.call(this,this):i)}:i:r}function Tm(r,i){return qo(ka(r),ka(i))}function ka(r){if(st(r)){const i={};for(let w=0;w1)return w&&at(i)?i.call(t&&t.proxy):i}}function Qd(){return!!(Zt||Kt||ro)}const Jd={},ef=()=>Object.create(Jd),tf=r=>Object.getPrototypeOf(r)===Jd;function Om(r,i,w,t=!1){const x={},v=ef();r.propsDefaults=Object.create(null),rf(r,i,x,v);for(const s in r.propsOptions[0])s in x||(x[s]=void 0);w?r.props=t?x:ps(x):r.type.props?r.props=x:r.props=v,r.attrs=v}function Pm(r,i,w,t){const{props:x,attrs:v,vnode:{patchFlag:s}}=r,u=vt(x),[o]=r.propsOptions;let f=!1;if((t||s>0)&&!(s&16)){if(s&8){const g=r.vnode.dynamicProps;for(let m=0;m{o=!0;const[n,a]=nf(m,i,!0);Qt(s,n),a&&u.push(...a)};!w&&i.mixins.length&&i.mixins.forEach(g),r.extends&&g(r.extends),r.mixins&&r.mixins.forEach(g)}if(!v&&!o)return At(r)&&t.set(r,_o),_o;if(st(v))for(let g=0;gr[0]==="_"||r==="$stable",_l=r=>st(r)?r.map(Br):[Br(r)],Rm=(r,i,w)=>{if(i._n)return i;const t=Ur((...x)=>_l(i(...x)),w);return t._c=!1,t},sf=(r,i,w)=>{const t=r._ctx;for(const x in r){if(of(x))continue;const v=r[x];if(at(v))i[x]=Rm(x,v,t);else if(v!=null){const s=_l(v);i[x]=()=>s}}},af=(r,i)=>{const w=_l(i);r.slots.default=()=>w},lf=(r,i,w)=>{for(const t in i)(w||t!=="_")&&(r[t]=i[t])},Lm=(r,i,w)=>{const t=r.slots=ef();if(r.vnode.shapeFlag&32){const x=i._;x?(lf(t,i,w),w&&ad(t,"_",x,!0)):sf(i,t)}else i&&af(r,i)},Im=(r,i,w)=>{const{vnode:t,slots:x}=r;let v=!0,s=Mt;if(t.shapeFlag&32){const u=i._;u?w&&u===1?v=!1:lf(x,i,w):(v=!i.$stable,sf(i,x)),s=i}else i&&(af(r,i),s={default:1});if(v)for(const u in x)!of(u)&&s[u]==null&&delete x[u]},lr=yf;function Dm(r){return uf(r)}function Fm(r){return uf(r,lm)}function uf(r,i){const w=ud();w.__VUE__=!0;const{insert:t,remove:x,patchProp:v,createElement:s,createText:u,createComment:o,setText:f,setElementText:g,parentNode:m,nextSibling:n,setScopeId:a=dn,insertStaticContent:l}=r,d=($,z,te,ce=null,me=null,de=null,ye=void 0,ve=null,ke=!!z.dynamicChildren)=>{if($===z)return;$&&!Qr($,z)&&(ce=Z($),le($,me,de,!0),$=null),z.patchFlag===-2&&(ke=!1,z.dynamicChildren=null);const{type:be,ref:Ne,shapeFlag:Re}=z;switch(be){case no:y($,z,te,ce);break;case $t:h($,z,te,ce);break;case $o:$==null&&c(z,te,ce,ye);break;case mr:I($,z,te,ce,me,de,ye,ve,ke);break;default:Re&1?j($,z,te,ce,me,de,ye,ve,ke):Re&6?A($,z,te,ce,me,de,ye,ve,ke):(Re&64||Re&128)&&be.process($,z,te,ce,me,de,ye,ve,ke,ue)}Ne!=null&&me&&ei(Ne,$&&$.ref,de,z||$,!z)},y=($,z,te,ce)=>{if($==null)t(z.el=u(z.children),te,ce);else{const me=z.el=$.el;z.children!==$.children&&f(me,z.children)}},h=($,z,te,ce)=>{$==null?t(z.el=o(z.children||""),te,ce):z.el=$.el},c=($,z,te,ce)=>{[$.el,$.anchor]=l($.children,z,te,ce,$.el,$.anchor)},p=({el:$,anchor:z},te,ce)=>{let me;for(;$&&$!==z;)me=n($),t($,te,ce),$=me;t(z,te,ce)},b=({el:$,anchor:z})=>{let te;for(;$&&$!==z;)te=n($),x($),$=te;x(z)},j=($,z,te,ce,me,de,ye,ve,ke)=>{z.type==="svg"?ye="svg":z.type==="math"&&(ye="mathml"),$==null?M(z,te,ce,me,de,ye,ve,ke):O($,z,me,de,ye,ve,ke)},M=($,z,te,ce,me,de,ye,ve)=>{let ke,be;const{props:Ne,shapeFlag:Re,transition:Ie,dirs:Fe}=$;if(ke=$.el=s($.type,de,Ne&&Ne.is,Ne),Re&8?g(ke,$.children):Re&16&&k($.children,ke,null,ce,me,Ki($,de),ye,ve),Fe&&cn($,null,ce,"created"),E(ke,$,$.scopeId,ye,ce),Ne){for(const xe in Ne)xe!=="value"&&!xo(xe)&&v(ke,xe,null,Ne[xe],de,ce);"value"in Ne&&v(ke,"value",null,Ne.value,de),(be=Ne.onVnodeBeforeMount)&&xr(be,ce,$)}Fe&&cn($,null,ce,"beforeMount");const Ge=cf(me,Ie);Ge&&Ie.beforeEnter(ke),t(ke,z,te),((be=Ne&&Ne.onVnodeMounted)||Ge||Fe)&&lr(()=>{be&&xr(be,ce,$),Ge&&Ie.enter(ke),Fe&&cn($,null,ce,"mounted")},me)},E=($,z,te,ce,me)=>{if(te&&a($,te),ce)for(let de=0;de{for(let be=ke;be<$.length;be++){const Ne=$[be]=ve?Rn($[be]):Br($[be]);d(null,Ne,z,te,ce,me,de,ye,ve)}},O=($,z,te,ce,me,de,ye)=>{const ve=z.el=$.el;let{patchFlag:ke,dynamicChildren:be,dirs:Ne}=z;ke|=$.patchFlag&16;const Re=$.props||Mt,Ie=z.props||Mt;let Fe;if(te&&Xn(te,!1),(Fe=Ie.onVnodeBeforeUpdate)&&xr(Fe,te,z,$),Ne&&cn(z,$,te,"beforeUpdate"),te&&Xn(te,!0),(Re.innerHTML&&Ie.innerHTML==null||Re.textContent&&Ie.textContent==null)&&g(ve,""),be?L($.dynamicChildren,be,ve,te,ce,Ki(z,me),de):ye||H($,z,ve,null,te,ce,Ki(z,me),de,!1),ke>0){if(ke&16)C(ve,Re,Ie,te,me);else if(ke&2&&Re.class!==Ie.class&&v(ve,"class",null,Ie.class,me),ke&4&&v(ve,"style",Re.style,Ie.style,me),ke&8){const Ge=z.dynamicProps;for(let xe=0;xe{Fe&&xr(Fe,te,z,$),Ne&&cn(z,$,te,"updated")},ce)},L=($,z,te,ce,me,de,ye)=>{for(let ve=0;ve{if(z!==te){if(z!==Mt)for(const de in z)!xo(de)&&!(de in te)&&v($,de,z[de],null,me,ce);for(const de in te){if(xo(de))continue;const ye=te[de],ve=z[de];ye!==ve&&de!=="value"&&v($,de,ve,ye,me,ce)}"value"in te&&v($,"value",z.value,te.value,me)}},I=($,z,te,ce,me,de,ye,ve,ke)=>{const be=z.el=$?$.el:u(""),Ne=z.anchor=$?$.anchor:u("");let{patchFlag:Re,dynamicChildren:Ie,slotScopeIds:Fe}=z;Fe&&(ve=ve?ve.concat(Fe):Fe),$==null?(t(be,te,ce),t(Ne,te,ce),k(z.children||[],te,Ne,me,de,ye,ve,ke)):Re>0&&Re&64&&Ie&&$.dynamicChildren?(L($.dynamicChildren,Ie,te,me,de,ye,ve),(z.key!=null||me&&z===me.subTree)&&df($,z,!0)):H($,z,te,Ne,me,de,ye,ve,ke)},A=($,z,te,ce,me,de,ye,ve,ke)=>{z.slotScopeIds=ve,$==null?z.shapeFlag&512?me.ctx.activate(z,te,ce,ye,ke):N(z,te,ce,me,de,ye,ke):F($,z,ke)},N=($,z,te,ce,me,de,ye)=>{const ve=$.component=sy($,ce,me);if(ys($)&&(ve.ctx.renderer=ue),iy(ve,!1,ye),ve.asyncDep){if(me&&me.registerDep(ve,B,ye),!$.el){const ke=ve.subTree=ft($t);h(null,ke,z,te)}}else B(ve,$,z,te,me,de,ye)},F=($,z,te)=>{const ce=z.component=$.component;if(Xm($,z,te))if(ce.asyncDep&&!ce.asyncResolved){W(ce,z,te);return}else ce.next=z,ce.update();else z.el=$.el,ce.vnode=z},B=($,z,te,ce,me,de,ye)=>{const ve=()=>{if($.isMounted){let{next:Re,bu:Ie,u:Fe,parent:Ge,vnode:xe}=$;{const Q=ff($);if(Q){Re&&(Re.el=xe.el,W($,Re,ye)),Q.asyncDep.then(()=>{$.isUnmounted||ve()});return}}let Le=Re,Ee;Xn($,!1),Re?(Re.el=xe.el,W($,Re,ye)):Re=xe,Ie&&jo(Ie),(Ee=Re.props&&Re.props.onVnodeBeforeUpdate)&&xr(Ee,Ge,Re,xe),Xn($,!0);const re=Qi($),se=$.subTree;$.subTree=re,d(se,re,m(se.el),Z(se),$,me,de),Re.el=re.el,Le===null&&xl($,re.el),Fe&&lr(Fe,me),(Ee=Re.props&&Re.props.onVnodeUpdated)&&lr(()=>xr(Ee,Ge,Re,xe),me)}else{let Re;const{el:Ie,props:Fe}=z,{bm:Ge,m:xe,parent:Le,root:Ee,type:re}=$,se=Un(z);if(Xn($,!1),Ge&&jo(Ge),!se&&(Re=Fe&&Fe.onVnodeBeforeMount)&&xr(Re,Le,z),Xn($,!0),Ie&&he){const Q=()=>{$.subTree=Qi($),he(Ie,$.subTree,$,me,null)};se&&re.__asyncHydrate?re.__asyncHydrate(Ie,$,Q):Q()}else{Ee.ce&&Ee.ce._injectChildStyle(re);const Q=$.subTree=Qi($);d(null,Q,te,ce,$,me,de),z.el=Q.el}if(xe&&lr(xe,me),!se&&(Re=Fe&&Fe.onVnodeMounted)){const Q=z;lr(()=>xr(Re,Le,Q),me)}(z.shapeFlag&256||Le&&Un(Le.vnode)&&Le.vnode.shapeFlag&256)&&$.a&&lr($.a,me),$.isMounted=!0,z=te=ce=null}};$.scope.on();const ke=$.effect=new pd(ve);$.scope.off();const be=$.update=ke.run.bind(ke),Ne=$.job=ke.runIfDirty.bind(ke);Ne.i=$,Ne.id=$.uid,ke.scheduler=()=>bi(Ne),Xn($,!0),be()},W=($,z,te)=>{z.component=$;const ce=$.vnode.props;$.vnode=z,$.next=null,Pm($,z.props,ce,te),Im($,z.children,te),zn(),Lu($),Wn()},H=($,z,te,ce,me,de,ye,ve,ke=!1)=>{const be=$&&$.children,Ne=$?$.shapeFlag:0,Re=z.children,{patchFlag:Ie,shapeFlag:Fe}=z;if(Ie>0){if(Ie&128){K(be,Re,te,ce,me,de,ye,ve,ke);return}else if(Ie&256){V(be,Re,te,ce,me,de,ye,ve,ke);return}}Fe&8?(Ne&16&&q(be,me,de),Re!==be&&g(te,Re)):Ne&16?Fe&16?K(be,Re,te,ce,me,de,ye,ve,ke):q(be,me,de,!0):(Ne&8&&g(te,""),Fe&16&&k(Re,te,ce,me,de,ye,ve,ke))},V=($,z,te,ce,me,de,ye,ve,ke)=>{$=$||_o,z=z||_o;const be=$.length,Ne=z.length,Re=Math.min(be,Ne);let Ie;for(Ie=0;IeNe?q($,me,de,!0,!1,Re):k(z,te,ce,me,de,ye,ve,ke,Re)},K=($,z,te,ce,me,de,ye,ve,ke)=>{let be=0;const Ne=z.length;let Re=$.length-1,Ie=Ne-1;for(;be<=Re&&be<=Ie;){const Fe=$[be],Ge=z[be]=ke?Rn(z[be]):Br(z[be]);if(Qr(Fe,Ge))d(Fe,Ge,te,null,me,de,ye,ve,ke);else break;be++}for(;be<=Re&&be<=Ie;){const Fe=$[Re],Ge=z[Ie]=ke?Rn(z[Ie]):Br(z[Ie]);if(Qr(Fe,Ge))d(Fe,Ge,te,null,me,de,ye,ve,ke);else break;Re--,Ie--}if(be>Re){if(be<=Ie){const Fe=Ie+1,Ge=FeIe)for(;be<=Re;)le($[be],me,de,!0),be++;else{const Fe=be,Ge=be,xe=new Map;for(be=Ge;be<=Ie;be++){const Se=z[be]=ke?Rn(z[be]):Br(z[be]);Se.key!=null&&xe.set(Se.key,be)}let Le,Ee=0;const re=Ie-Ge+1;let se=!1,Q=0;const ae=new Array(re);for(be=0;be=re){le(Se,me,de,!0);continue}let Pe;if(Se.key!=null)Pe=xe.get(Se.key);else for(Le=Ge;Le<=Ie;Le++)if(ae[Le-Ge]===0&&Qr(Se,z[Le])){Pe=Le;break}Pe===void 0?le(Se,me,de,!0):(ae[Pe-Ge]=be+1,Pe>=Q?Q=Pe:se=!0,d(Se,z[Pe],te,null,me,de,ye,ve,ke),Ee++)}const we=se?Nm(ae):_o;for(Le=we.length-1,be=re-1;be>=0;be--){const Se=Ge+be,Pe=z[Se],He=Se+1{const{el:de,type:ye,transition:ve,children:ke,shapeFlag:be}=$;if(be&6){J($.component.subTree,z,te,ce);return}if(be&128){$.suspense.move(z,te,ce);return}if(be&64){ye.move($,z,te,ue);return}if(ye===mr){t(de,z,te);for(let Re=0;Reve.enter(de),me);else{const{leave:Re,delayLeave:Ie,afterLeave:Fe}=ve,Ge=()=>t(de,z,te),xe=()=>{Re(de,()=>{Ge(),Fe&&Fe()})};Ie?Ie(de,Ge,xe):xe()}else t(de,z,te)},le=($,z,te,ce=!1,me=!1)=>{const{type:de,props:ye,ref:ve,children:ke,dynamicChildren:be,shapeFlag:Ne,patchFlag:Re,dirs:Ie,cacheIndex:Fe}=$;if(Re===-2&&(me=!1),ve!=null&&ei(ve,null,te,$,!0),Fe!=null&&(z.renderCache[Fe]=void 0),Ne&256){z.ctx.deactivate($);return}const Ge=Ne&1&&Ie,xe=!Un($);let Le;if(xe&&(Le=ye&&ye.onVnodeBeforeUnmount)&&xr(Le,z,$),Ne&6)G($.component,te,ce);else{if(Ne&128){$.suspense.unmount(te,ce);return}Ge&&cn($,null,z,"beforeUnmount"),Ne&64?$.type.remove($,z,te,ue,ce):be&&!be.hasOnce&&(de!==mr||Re>0&&Re&64)?q(be,z,te,!1,!0):(de===mr&&Re&384||!me&&Ne&16)&&q(ke,z,te),ce&&T($)}(xe&&(Le=ye&&ye.onVnodeUnmounted)||Ge)&&lr(()=>{Le&&xr(Le,z,$),Ge&&cn($,null,z,"unmounted")},te)},T=$=>{const{type:z,el:te,anchor:ce,transition:me}=$;if(z===mr){D(te,ce);return}if(z===$o){b($);return}const de=()=>{x(te),me&&!me.persisted&&me.afterLeave&&me.afterLeave()};if($.shapeFlag&1&&me&&!me.persisted){const{leave:ye,delayLeave:ve}=me,ke=()=>ye(te,de);ve?ve($.el,de,ke):ke()}else de()},D=($,z)=>{let te;for(;$!==z;)te=n($),x($),$=te;x(z)},G=($,z,te)=>{const{bum:ce,scope:me,job:de,subTree:ye,um:ve,m:ke,a:be}=$;ri(ke),ri(be),ce&&jo(ce),me.stop(),de&&(de.flags|=8,le(ye,$,z,te)),ve&&lr(ve,z),lr(()=>{$.isUnmounted=!0},z),z&&z.pendingBranch&&!z.isUnmounted&&$.asyncDep&&!$.asyncResolved&&$.suspenseId===z.pendingId&&(z.deps--,z.deps===0&&z.resolve())},q=($,z,te,ce=!1,me=!1,de=0)=>{for(let ye=de;ye<$.length;ye++)le($[ye],z,te,ce,me)},Z=$=>{if($.shapeFlag&6)return Z($.component.subTree);if($.shapeFlag&128)return $.suspense.next();const z=n($.anchor||$.el),te=z&&z[tm];return te?n(te):z};let ee=!1;const ne=($,z,te)=>{$==null?z._vnode&&le(z._vnode,null,null,!0):d(z._vnode||null,$,z,null,null,null,te),z._vnode=$,ee||(ee=!0,Lu(),Qs(),ee=!1)},ue={p:d,um:le,m:J,r:T,mt:N,mc:k,pc:H,pbc:L,n:Z,o:r};let ie,he;return i&&([ie,he]=i(ue)),{render:ne,hydrate:ie,createApp:Cm(ne,ie)}}function Ki({type:r,props:i},w){return w==="svg"&&r==="foreignObject"||w==="mathml"&&r==="annotation-xml"&&i&&i.encoding&&i.encoding.includes("html")?void 0:w}function Xn({effect:r,job:i},w){w?(r.flags|=32,i.flags|=4):(r.flags&=-33,i.flags&=-5)}function cf(r,i){return(!r||r&&!r.pendingBranch)&&i&&!i.persisted}function df(r,i,w=!1){const t=r.children,x=i.children;if(st(t)&&st(x))for(let v=0;v>1,r[w[u]]0&&(i[t]=w[v-1]),w[v]=t)}}for(v=w.length,s=w[v-1];v-- >0;)w[v]=s,s=i[s];return w}function ff(r){const i=r.subTree.component;if(i)return i.asyncDep&&!i.asyncResolved?i:ff(i)}function ri(r){if(r)for(let i=0;izt(Um);function fn(r,i){return wl(r,null,i)}function Bn(r,i,w){return wl(r,i,w)}function wl(r,i,w=Mt){const{immediate:t,deep:x,flush:v,once:s}=w,u=Qt({},w);let o;if(_s)if(v==="sync"){const n=Bm();o=n.__watcherHandles||(n.__watcherHandles=[])}else if(!i||t)u.once=!0;else return{stop:dn,resume:dn,pause:dn};const f=Zt;u.call=(n,a,l)=>rn(n,f,a,l);let g=!1;v==="post"?u.scheduler=n=>{lr(n,f&&f.suspense)}:v!=="sync"&&(g=!0,u.scheduler=(n,a)=>{a?n():bi(n)}),u.augmentJob=n=>{i&&(n.flags|=4),g&&(n.flags|=2,f&&(n.id=f.uid,n.i=f))};const m=Qp(r,i,u);return o&&o.push(m),m}function Gm(r,i,w){const t=this.proxy,x=Ut(r)?r.includes(".")?hf(t,r):()=>t[r]:r.bind(t,t);let v;at(i)?v=i:(v=i.handler,w=i);const s=oo(this),u=wl(x,v.bind(t),w);return s(),u}function hf(r,i){const w=i.split(".");return()=>{let t=r;for(let x=0;xi==="modelValue"||i==="model-value"?r.modelModifiers:r[`${i}Modifiers`]||r[`${tn(i)}Modifiers`]||r[`${io(i)}Modifiers`];function Hm(r,i,...w){if(r.isUnmounted)return;const t=r.vnode.props||Mt;let x=w;const v=i.startsWith("update:"),s=v&&Vm(t,i.slice(7));s&&(s.trim&&(x=w.map(g=>Ut(g)?g.trim():g)),s.number&&(x=w.map(ba)));let u,o=t[u=Vi(i)]||t[u=Vi(tn(i))];!o&&v&&(o=t[u=Vi(io(i))]),o&&rn(o,r,6,x);const f=t[u+"Once"];if(f){if(!r.emitted)r.emitted={};else if(r.emitted[u])return;r.emitted[u]=!0,rn(f,r,6,x)}}function pf(r,i,w=!1){const t=i.emitsCache,x=t.get(r);if(x!==void 0)return x;const v=r.emits;let s={},u=!1;if(!at(r)){const o=f=>{const g=pf(f,i,!0);g&&(u=!0,Qt(s,g))};!w&&i.mixins.length&&i.mixins.forEach(o),r.extends&&o(r.extends),r.mixins&&r.mixins.forEach(o)}return!v&&!u?(At(r)&&t.set(r,null),null):(st(v)?v.forEach(o=>s[o]=null):Qt(s,v),At(r)&&t.set(r,s),s)}function wi(r,i){return!r||!fs(i)?!1:(i=i.slice(2).replace(/Once$/,""),_t(r,i[0].toLowerCase()+i.slice(1))||_t(r,io(i))||_t(r,i))}function Qi(r){const{type:i,vnode:w,proxy:t,withProxy:x,propsOptions:[v],slots:s,attrs:u,emit:o,render:f,renderCache:g,props:m,data:n,setupState:a,ctx:l,inheritAttrs:d}=r,y=Js(r);let h,c;try{if(w.shapeFlag&4){const b=x||t,j=b;h=Br(f.call(j,b,g,m,a,n,l)),c=u}else{const b=i;h=Br(b.length>1?b(m,{attrs:u,slots:s,emit:o}):b(m,null)),c=i.props?u:Wm(u)}}catch(b){Zo.length=0,Po(b,r,1),h=ft($t)}let p=h;if(c&&d!==!1){const b=Object.keys(c),{shapeFlag:j}=p;b.length&&j&7&&(v&&b.some(ol)&&(c=qm(c,v)),p=hn(p,c,!1,!0))}return w.dirs&&(p=hn(p,null,!1,!0),p.dirs=p.dirs?p.dirs.concat(w.dirs):w.dirs),w.transition&&To(p,w.transition),h=p,Js(y),h}function zm(r,i=!0){let w;for(let t=0;t{let i;for(const w in r)(w==="class"||w==="style"||fs(w))&&((i||(i={}))[w]=r[w]);return i},qm=(r,i)=>{const w={};for(const t in r)(!ol(t)||!(t.slice(9)in i))&&(w[t]=r[t]);return w};function Xm(r,i,w){const{props:t,children:x,component:v}=r,{props:s,children:u,patchFlag:o}=i,f=v.emitsOptions;if(i.dirs||i.transition)return!0;if(w&&o>=0){if(o&1024)return!0;if(o&16)return t?zu(t,s,f):!!s;if(o&8){const g=i.dynamicProps;for(let m=0;mr.__isSuspense;let Ca=0;const Ym={name:"Suspense",__isSuspense:!0,process(r,i,w,t,x,v,s,u,o,f){if(r==null)$m(i,w,t,x,v,s,u,o,f);else{if(v&&v.deps>0&&!r.suspense.isInFallback){i.suspense=r.suspense,i.suspense.vnode=i,i.el=r.el;return}Zm(r,i,w,t,x,s,u,o,f)}},hydrate:Km,normalize:Qm},jl=Ym;function as(r,i){const w=r.props&&r.props[i];at(w)&&w()}function $m(r,i,w,t,x,v,s,u,o){const{p:f,o:{createElement:g}}=o,m=g("div"),n=r.suspense=mf(r,x,t,i,m,w,v,s,u,o);f(null,n.pendingBranch=r.ssContent,m,null,t,n,v,s),n.deps>0?(as(r,"onPending"),as(r,"onFallback"),f(null,r.ssFallback,i,w,t,null,v,s),Eo(n,r.ssFallback)):n.resolve(!1,!0)}function Zm(r,i,w,t,x,v,s,u,{p:o,um:f,o:{createElement:g}}){const m=i.suspense=r.suspense;m.vnode=i,i.el=r.el;const n=i.ssContent,a=i.ssFallback,{activeBranch:l,pendingBranch:d,isInFallback:y,isHydrating:h}=m;if(d)m.pendingBranch=n,Qr(n,d)?(o(d,n,m.hiddenContainer,null,x,m,v,s,u),m.deps<=0?m.resolve():y&&(h||(o(l,a,w,t,x,null,v,s,u),Eo(m,a)))):(m.pendingId=Ca++,h?(m.isHydrating=!1,m.activeBranch=d):f(d,x,m),m.deps=0,m.effects.length=0,m.hiddenContainer=g("div"),y?(o(null,n,m.hiddenContainer,null,x,m,v,s,u),m.deps<=0?m.resolve():(o(l,a,w,t,x,null,v,s,u),Eo(m,a))):l&&Qr(n,l)?(o(l,n,w,t,x,m,v,s,u),m.resolve(!0)):(o(null,n,m.hiddenContainer,null,x,m,v,s,u),m.deps<=0&&m.resolve()));else if(l&&Qr(n,l))o(l,n,w,t,x,m,v,s,u),Eo(m,n);else if(as(i,"onPending"),m.pendingBranch=n,n.shapeFlag&512?m.pendingId=n.component.suspenseId:m.pendingId=Ca++,o(null,n,m.hiddenContainer,null,x,m,v,s,u),m.deps<=0)m.resolve();else{const{timeout:c,pendingId:p}=m;c>0?setTimeout(()=>{m.pendingId===p&&m.fallback(a)},c):c===0&&m.fallback(a)}}function mf(r,i,w,t,x,v,s,u,o,f,g=!1){const{p:m,m:n,um:a,n:l,o:{parentNode:d,remove:y}}=f;let h;const c=Jm(r);c&&i&&i.pendingBranch&&(h=i.pendingId,i.deps++);const p=r.props?ld(r.props.timeout):void 0,b=v,j={vnode:r,parent:i,parentComponent:w,namespace:s,container:t,hiddenContainer:x,deps:0,pendingId:Ca++,timeout:typeof p=="number"?p:-1,activeBranch:null,pendingBranch:null,isInFallback:!g,isHydrating:g,isUnmounted:!1,effects:[],resolve(M=!1,E=!1){const{vnode:k,activeBranch:O,pendingBranch:L,pendingId:C,effects:I,parentComponent:A,container:N}=j;let F=!1;j.isHydrating?j.isHydrating=!1:M||(F=O&&L.transition&&L.transition.mode==="out-in",F&&(O.transition.afterLeave=()=>{C===j.pendingId&&(n(L,N,v===b?l(O):v,0),ja(I))}),O&&(d(O.el)===N&&(v=l(O)),a(O,A,j,!0)),F||n(L,N,v,0)),Eo(j,L),j.pendingBranch=null,j.isInFallback=!1;let B=j.parent,W=!1;for(;B;){if(B.pendingBranch){B.effects.push(...I),W=!0;break}B=B.parent}!W&&!F&&ja(I),j.effects=[],c&&i&&i.pendingBranch&&h===i.pendingId&&(i.deps--,i.deps===0&&!E&&i.resolve()),as(k,"onResolve")},fallback(M){if(!j.pendingBranch)return;const{vnode:E,activeBranch:k,parentComponent:O,container:L,namespace:C}=j;as(E,"onFallback");const I=l(k),A=()=>{j.isInFallback&&(m(null,M,L,I,O,null,C,u,o),Eo(j,M))},N=M.transition&&M.transition.mode==="out-in";N&&(k.transition.afterLeave=A),j.isInFallback=!0,a(k,O,null,!0),N||A()},move(M,E,k){j.activeBranch&&n(j.activeBranch,M,E,k),j.container=M},next(){return j.activeBranch&&l(j.activeBranch)},registerDep(M,E,k){const O=!!j.pendingBranch;O&&j.deps++;const L=M.vnode.el;M.asyncDep.catch(C=>{Po(C,M,0)}).then(C=>{if(M.isUnmounted||j.isUnmounted||j.pendingId!==M.suspenseId)return;M.asyncResolved=!0;const{vnode:I}=M;Aa(M,C,!1),L&&(I.el=L);const A=!L&&M.subTree.el;E(M,I,d(L||M.subTree.el),L?null:l(M.subTree),j,s,k),A&&y(A),xl(M,I.el),O&&--j.deps===0&&j.resolve()})},unmount(M,E){j.isUnmounted=!0,j.activeBranch&&a(j.activeBranch,w,M,E),j.pendingBranch&&a(j.pendingBranch,w,M,E)}};return j}function Km(r,i,w,t,x,v,s,u,o){const f=i.suspense=mf(i,t,w,r.parentNode,document.createElement("div"),null,x,v,s,u,!0),g=o(r,f.pendingBranch=i.ssContent,w,f,v,s);return f.deps===0&&f.resolve(!1,!0),g}function Qm(r){const{shapeFlag:i,children:w}=r,t=i&32;r.ssContent=Wu(t?w.default:w),r.ssFallback=t?Wu(w.fallback):ft($t)}function Wu(r){let i;if(at(r)){const w=ko&&r._c;w&&(r._d=!1,jr()),r=r(),w&&(r._d=!0,i=Sr,gf())}return st(r)&&(r=zm(r)),r=Br(r),i&&!r.dynamicChildren&&(r.dynamicChildren=i.filter(w=>w!==r)),r}function yf(r,i){i&&i.pendingBranch?st(r)?i.effects.push(...r):i.effects.push(r):ja(r)}function Eo(r,i){r.activeBranch=i;const{vnode:w,parentComponent:t}=r;let x=i.el;for(;!x&&i.component;)i=i.component.subTree,x=i.el;w.el=x,t&&t.subTree===w&&(t.vnode.el=x,xl(t,x))}function Jm(r){const i=r.props&&r.props.suspensible;return i!=null&&i!==!1}const mr=Symbol.for("v-fgt"),no=Symbol.for("v-txt"),$t=Symbol.for("v-cmt"),$o=Symbol.for("v-stc"),Zo=[];let Sr=null;function jr(r=!1){Zo.push(Sr=r?null:[])}function gf(){Zo.pop(),Sr=Zo[Zo.length-1]||null}let ko=1;function qu(r){ko+=r,r<0&&Sr&&(Sr.hasOnce=!0)}function vf(r){return r.dynamicChildren=ko>0?Sr||_o:null,gf(),ko>0&&Sr&&Sr.push(r),r}function bs(r,i,w,t,x,v){return vf(Pt(r,i,w,t,x,v,!0))}function Dn(r,i,w,t,x){return vf(ft(r,i,w,t,x,!0))}function Mo(r){return r?r.__v_isVNode===!0:!1}function Qr(r,i){return r.type===i.type&&r.key===i.key}const bf=({key:r})=>r??null,qs=({ref:r,ref_key:i,ref_for:w})=>(typeof r=="number"&&(r=""+r),r!=null?Ut(r)||nr(r)||at(r)?{i:Kt,r,k:i,f:!!w}:r:null);function Pt(r,i=null,w=null,t=0,x=null,v=r===mr?0:1,s=!1,u=!1){const o={__v_isVNode:!0,__v_skip:!0,type:r,props:i,key:i&&bf(i),ref:i&&qs(i),scopeId:Ld,slotScopeIds:null,children:w,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:v,patchFlag:t,dynamicProps:x,dynamicChildren:null,appContext:null,ctx:Kt};return u?(Sl(o,w),v&128&&r.normalize(o)):w&&(o.shapeFlag|=Ut(w)?8:16),ko>0&&!s&&Sr&&(o.patchFlag>0||v&6)&&o.patchFlag!==32&&Sr.push(o),o}const ft=ey;function ey(r,i=null,w=null,t=0,x=null,v=!1){if((!r||r===Xd)&&(r=$t),Mo(r)){const u=hn(r,i,!0);return w&&Sl(u,w),ko>0&&!v&&Sr&&(u.shapeFlag&6?Sr[Sr.indexOf(r)]=u:Sr.push(u)),u.patchFlag=-2,u}if(uy(r)&&(r=r.__vccOpts),i){i=ty(i);let{class:u,style:o}=i;u&&!Ut(u)&&(i.class=Jn(u)),At(o)&&(ml(o)&&!st(o)&&(o=Qt({},o)),i.style=ll(o))}const s=Ut(r)?1:ni(r)?128:Id(r)?64:At(r)?4:at(r)?2:0;return Pt(r,i,w,t,x,s,v,!0)}function ty(r){return r?ml(r)||tf(r)?Qt({},r):r:null}function hn(r,i,w=!1,t=!1){const{props:x,ref:v,patchFlag:s,children:u,transition:o}=r,f=i?_f(x||{},i):x,g={__v_isVNode:!0,__v_skip:!0,type:r.type,props:f,key:f&&bf(f),ref:i&&i.ref?w&&v?st(v)?v.concat(qs(i)):[v,qs(i)]:qs(i):v,scopeId:r.scopeId,slotScopeIds:r.slotScopeIds,children:u,target:r.target,targetStart:r.targetStart,targetAnchor:r.targetAnchor,staticCount:r.staticCount,shapeFlag:r.shapeFlag,patchFlag:i&&r.type!==mr?s===-1?16:s|16:s,dynamicProps:r.dynamicProps,dynamicChildren:r.dynamicChildren,appContext:r.appContext,dirs:r.dirs,transition:o,component:r.component,suspense:r.suspense,ssContent:r.ssContent&&hn(r.ssContent),ssFallback:r.ssFallback&&hn(r.ssFallback),el:r.el,anchor:r.anchor,ctx:r.ctx,ce:r.ce};return o&&t&&To(g,o.clone(g)),g}function Ko(r=" ",i=0){return ft(no,null,r,i)}function ry(r,i){const w=ft($o,null,r);return w.staticCount=i,w}function aw(r="",i=!1){return i?(jr(),Dn($t,null,r)):ft($t,null,r)}function Br(r){return r==null||typeof r=="boolean"?ft($t):st(r)?ft(mr,null,r.slice()):typeof r=="object"?Rn(r):ft(no,null,String(r))}function Rn(r){return r.el===null&&r.patchFlag!==-1||r.memo?r:hn(r)}function Sl(r,i){let w=0;const{shapeFlag:t}=r;if(i==null)i=null;else if(st(i))w=16;else if(typeof i=="object")if(t&65){const x=i.default;x&&(x._c&&(x._d=!1),Sl(r,x()),x._c&&(x._d=!0));return}else{w=32;const x=i._;!x&&!tf(i)?i._ctx=Kt:x===3&&Kt&&(Kt.slots._===1?i._=1:(i._=2,r.patchFlag|=1024))}else at(i)?(i={default:i,_ctx:Kt},w=32):(i=String(i),t&64?(w=16,i=[Ko(i)]):w=8);r.children=i,r.shapeFlag|=w}function _f(...r){const i={};for(let w=0;wZt||Kt;let oi,Oa;{const r=ud(),i=(w,t)=>{let x;return(x=r[w])||(x=r[w]=[]),x.push(t),v=>{x.length>1?x.forEach(s=>s(v)):x[0](v)}};oi=i("__VUE_INSTANCE_SETTERS__",w=>Zt=w),Oa=i("__VUE_SSR_SETTERS__",w=>_s=w)}const oo=r=>{const i=Zt;return oi(r),r.scope.on(),()=>{r.scope.off(),oi(i)}},Pa=()=>{Zt&&Zt.scope.off(),oi(null)};function wf(r){return r.vnode.shapeFlag&4}let _s=!1;function iy(r,i=!1,w=!1){i&&Oa(i);const{props:t,children:x}=r.vnode,v=wf(r);Om(r,t,v,i),Lm(r,x,w);const s=v?ay(r,i):void 0;return i&&Oa(!1),s}function ay(r,i){const w=r.type;r.accessCache=Object.create(null),r.proxy=new Proxy(r.ctx,wm);const{setup:t}=w;if(t){const x=r.setupContext=t.length>1?jf(r):null,v=oo(r);zn();const s=ms(t,r,0,[r.props,x]);if(Wn(),v(),il(s)){if(Un(r)||vl(r),s.then(Pa,Pa),i)return s.then(u=>{Aa(r,u,i)}).catch(u=>{Po(u,r,0)});r.asyncDep=s}else Aa(r,s,i)}else xf(r,i)}function Aa(r,i,w){at(i)?r.type.__ssrInlineRender?r.ssrRender=i:r.render=i:At(i)&&(r.setupState=Cd(i)),xf(r,w)}let Xu;function xf(r,i,w){const t=r.type;if(!r.render){if(!i&&Xu&&!t.render){const x=t.template||bl(r).template;if(x){const{isCustomElement:v,compilerOptions:s}=r.appContext.config,{delimiters:u,compilerOptions:o}=t,f=Qt(Qt({isCustomElement:v,delimiters:u},s),o);t.render=Xu(x,f)}}r.render=t.render||dn}{const x=oo(r);zn();try{jm(r)}finally{Wn(),x()}}}const ly={get(r,i){return yr(r,"get",""),r[i]}};function jf(r){const i=w=>{r.exposed=w||{}};return{attrs:new Proxy(r.attrs,ly),slots:r.slots,emit:r.emit,expose:i}}function xi(r){return r.exposed?r.exposeProxy||(r.exposeProxy=new Proxy(Cd(Vp(r.exposed)),{get(i,w){if(w in i)return i[w];if(w in Yo)return Yo[w](r)},has(i,w){return w in i||w in Yo}})):r.proxy}function Ra(r,i=!0){return at(r)?r.displayName||r.name:r.name||i&&r.__name}function uy(r){return at(r)&&"__vccOpts"in r}const jt=(r,i)=>Zp(r,i,_s);function or(r,i,w){const t=arguments.length;return t===2?At(i)&&!st(i)?Mo(i)?ft(r,null,[i]):ft(r,i):ft(r,null,i):(t>3?w=Array.prototype.slice.call(arguments,2):t===3&&Mo(w)&&(w=[w]),ft(r,i,w))}const Sf="3.5.4";/** -* @vue/runtime-dom v3.5.4 -* (c) 2018-present Yuxi (Evan) You and Vue contributors -* @license MIT -**/let La;const Yu=typeof window<"u"&&window.trustedTypes;if(Yu)try{La=Yu.createPolicy("vue",{createHTML:r=>r})}catch{}const Ef=La?r=>La.createHTML(r):r=>r,cy="http://www.w3.org/2000/svg",dy="http://www.w3.org/1998/Math/MathML",vn=typeof document<"u"?document:null,$u=vn&&vn.createElement("template"),fy={insert:(r,i,w)=>{i.insertBefore(r,w||null)},remove:r=>{const i=r.parentNode;i&&i.removeChild(r)},createElement:(r,i,w,t)=>{const x=i==="svg"?vn.createElementNS(cy,r):i==="mathml"?vn.createElementNS(dy,r):w?vn.createElement(r,{is:w}):vn.createElement(r);return r==="select"&&t&&t.multiple!=null&&x.setAttribute("multiple",t.multiple),x},createText:r=>vn.createTextNode(r),createComment:r=>vn.createComment(r),setText:(r,i)=>{r.nodeValue=i},setElementText:(r,i)=>{r.textContent=i},parentNode:r=>r.parentNode,nextSibling:r=>r.nextSibling,querySelector:r=>vn.querySelector(r),setScopeId(r,i){r.setAttribute(i,"")},insertStaticContent(r,i,w,t,x,v){const s=w?w.previousSibling:i.lastChild;if(x&&(x===v||x.nextSibling))for(;i.insertBefore(x.cloneNode(!0),w),!(x===v||!(x=x.nextSibling)););else{$u.innerHTML=Ef(t==="svg"?`${r}`:t==="mathml"?`${r}`:r);const u=$u.content;if(t==="svg"||t==="mathml"){const o=u.firstChild;for(;o.firstChild;)u.appendChild(o.firstChild);u.removeChild(o)}i.insertBefore(u,w)}return[s?s.nextSibling:i.firstChild,w?w.previousSibling:i.lastChild]}},Cn="transition",Ho="animation",ls=Symbol("_vtc"),Tf={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},hy=Qt({},Dd,Tf),py=r=>(r.displayName="Transition",r.props=hy,r),El=py((r,{slots:i})=>or(om,my(r),i)),Yn=(r,i=[])=>{st(r)?r.forEach(w=>w(...i)):r&&r(...i)},Zu=r=>r?st(r)?r.some(i=>i.length>1):r.length>1:!1;function my(r){const i={};for(const I in r)I in Tf||(i[I]=r[I]);if(r.css===!1)return i;const{name:w="v",type:t,duration:x,enterFromClass:v=`${w}-enter-from`,enterActiveClass:s=`${w}-enter-active`,enterToClass:u=`${w}-enter-to`,appearFromClass:o=v,appearActiveClass:f=s,appearToClass:g=u,leaveFromClass:m=`${w}-leave-from`,leaveActiveClass:n=`${w}-leave-active`,leaveToClass:a=`${w}-leave-to`}=r,l=yy(x),d=l&&l[0],y=l&&l[1],{onBeforeEnter:h,onEnter:c,onEnterCancelled:p,onLeave:b,onLeaveCancelled:j,onBeforeAppear:M=h,onAppear:E=c,onAppearCancelled:k=p}=i,O=(I,A,N)=>{$n(I,A?g:u),$n(I,A?f:s),N&&N()},L=(I,A)=>{I._isLeaving=!1,$n(I,m),$n(I,a),$n(I,n),A&&A()},C=I=>(A,N)=>{const F=I?E:c,B=()=>O(A,I,N);Yn(F,[A,B]),Ku(()=>{$n(A,I?o:v),On(A,I?g:u),Zu(F)||Qu(A,t,d,B)})};return Qt(i,{onBeforeEnter(I){Yn(h,[I]),On(I,v),On(I,s)},onBeforeAppear(I){Yn(M,[I]),On(I,o),On(I,f)},onEnter:C(!1),onAppear:C(!0),onLeave(I,A){I._isLeaving=!0;const N=()=>L(I,A);On(I,m),On(I,n),by(),Ku(()=>{I._isLeaving&&($n(I,m),On(I,a),Zu(b)||Qu(I,t,y,N))}),Yn(b,[I,N])},onEnterCancelled(I){O(I,!1),Yn(p,[I])},onAppearCancelled(I){O(I,!0),Yn(k,[I])},onLeaveCancelled(I){L(I),Yn(j,[I])}})}function yy(r){if(r==null)return null;if(At(r))return[Ji(r.enter),Ji(r.leave)];{const i=Ji(r);return[i,i]}}function Ji(r){return ld(r)}function On(r,i){i.split(/\s+/).forEach(w=>w&&r.classList.add(w)),(r[ls]||(r[ls]=new Set)).add(i)}function $n(r,i){i.split(/\s+/).forEach(t=>t&&r.classList.remove(t));const w=r[ls];w&&(w.delete(i),w.size||(r[ls]=void 0))}function Ku(r){requestAnimationFrame(()=>{requestAnimationFrame(r)})}let gy=0;function Qu(r,i,w,t){const x=r._endId=++gy,v=()=>{x===r._endId&&t()};if(w)return setTimeout(v,w);const{type:s,timeout:u,propCount:o}=vy(r,i);if(!s)return t();const f=s+"end";let g=0;const m=()=>{r.removeEventListener(f,n),v()},n=a=>{a.target===r&&++g>=o&&m()};setTimeout(()=>{g(w[l]||"").split(", "),x=t(`${Cn}Delay`),v=t(`${Cn}Duration`),s=Ju(x,v),u=t(`${Ho}Delay`),o=t(`${Ho}Duration`),f=Ju(u,o);let g=null,m=0,n=0;i===Cn?s>0&&(g=Cn,m=s,n=v.length):i===Ho?f>0&&(g=Ho,m=f,n=o.length):(m=Math.max(s,f),g=m>0?s>f?Cn:Ho:null,n=g?g===Cn?v.length:o.length:0);const a=g===Cn&&/\b(transform|all)(,|$)/.test(t(`${Cn}Property`).toString());return{type:g,timeout:m,propCount:n,hasTransform:a}}function Ju(r,i){for(;r.lengthec(w)+ec(r[t])))}function ec(r){return r==="auto"?0:Number(r.slice(0,-1).replace(",","."))*1e3}function by(){return document.body.offsetHeight}function _y(r,i,w){const t=r[ls];t&&(i=(i?[i,...t]:[...t]).join(" ")),i==null?r.removeAttribute("class"):w?r.setAttribute("class",i):r.className=i}const tc=Symbol("_vod"),wy=Symbol("_vsh"),xy=Symbol(""),jy=/(^|;)\s*display\s*:/;function Sy(r,i,w){const t=r.style,x=Ut(w);let v=!1;if(w&&!x){if(i)if(Ut(i))for(const s of i.split(";")){const u=s.slice(0,s.indexOf(":")).trim();w[u]==null&&Xs(t,u,"")}else for(const s in i)w[s]==null&&Xs(t,s,"");for(const s in w)s==="display"&&(v=!0),Xs(t,s,w[s])}else if(x){if(i!==w){const s=t[xy];s&&(w+=";"+s),t.cssText=w,v=jy.test(w)}}else i&&r.removeAttribute("style");tc in r&&(r[tc]=v?t.display:"",r[wy]&&(t.display="none"))}const rc=/\s*!important$/;function Xs(r,i,w){if(st(w))w.forEach(t=>Xs(r,i,t));else if(w==null&&(w=""),i.startsWith("--"))r.setProperty(i,w);else{const t=Ey(r,i);rc.test(w)?r.setProperty(io(t),w.replace(rc,""),"important"):r[t]=w}}const nc=["Webkit","Moz","ms"],ea={};function Ey(r,i){const w=ea[i];if(w)return w;let t=tn(i);if(t!=="filter"&&t in r)return ea[i]=t;t=mi(t);for(let x=0;xta||(Oy.then(()=>ta=0),ta=Date.now());function Ay(r,i){const w=t=>{if(!t._vts)t._vts=Date.now();else if(t._vts<=w.attached)return;rn(Ry(t,w.value),i,5,[t])};return w.value=r,w.attached=Py(),w}function Ry(r,i){if(st(i)){const w=r.stopImmediatePropagation;return r.stopImmediatePropagation=()=>{w.call(r),r._stopped=!0},i.map(t=>x=>!x._stopped&&t&&t(x))}else return i}const lc=r=>r.charCodeAt(0)===111&&r.charCodeAt(1)===110&&r.charCodeAt(2)>96&&r.charCodeAt(2)<123,Ly=(r,i,w,t,x,v)=>{const s=x==="svg";i==="class"?_y(r,t,s):i==="style"?Sy(r,w,t):fs(i)?ol(i)||My(r,i,w,t,v):(i[0]==="."?(i=i.slice(1),!0):i[0]==="^"?(i=i.slice(1),!1):Iy(r,i,t,s))?(Ty(r,i,t),!r.tagName.includes("-")&&(i==="value"||i==="checked"||i==="selected")&&sc(r,i,t,s,v,i!=="value")):(i==="true-value"?r._trueValue=t:i==="false-value"&&(r._falseValue=t),sc(r,i,t,s))};function Iy(r,i,w,t){if(t)return!!(i==="innerHTML"||i==="textContent"||i in r&&lc(i)&&at(w));if(i==="spellcheck"||i==="draggable"||i==="translate"||i==="form"||i==="list"&&r.tagName==="INPUT"||i==="type"&&r.tagName==="TEXTAREA")return!1;if(i==="width"||i==="height"){const x=r.tagName;if(x==="IMG"||x==="VIDEO"||x==="CANVAS"||x==="SOURCE")return!1}return lc(i)&&Ut(w)?!1:!!(i in r||r._isVueCE&&(/[A-Z]/.test(i)||!Ut(w)))}const uc=r=>{const i=r.props["onUpdate:modelValue"]||!1;return st(i)?w=>jo(i,w):i};function Dy(r){r.target.composing=!0}function cc(r){const i=r.target;i.composing&&(i.composing=!1,i.dispatchEvent(new Event("input")))}const ra=Symbol("_assign"),lw={created(r,{modifiers:{lazy:i,trim:w,number:t}},x){r[ra]=uc(x);const v=t||x.props&&x.props.type==="number";yo(r,i?"change":"input",s=>{if(s.target.composing)return;let u=r.value;w&&(u=u.trim()),v&&(u=ba(u)),r[ra](u)}),w&&yo(r,"change",()=>{r.value=r.value.trim()}),i||(yo(r,"compositionstart",Dy),yo(r,"compositionend",cc),yo(r,"change",cc))},mounted(r,{value:i}){r.value=i??""},beforeUpdate(r,{value:i,oldValue:w,modifiers:{lazy:t,trim:x,number:v}},s){if(r[ra]=uc(s),r.composing)return;const u=(v||r.type==="number")&&!/^0\d/.test(r.value)?ba(r.value):r.value,o=i??"";u!==o&&(document.activeElement===r&&r.type!=="range"&&(t&&i===w||x&&r.value.trim()===o)||(r.value=o))}},kf=Qt({patchProp:Ly},fy);let Qo,dc=!1;function Fy(){return Qo||(Qo=Dm(kf))}function Ny(){return Qo=dc?Qo:Fm(kf),dc=!0,Qo}const Uy=(...r)=>{const i=Fy().createApp(...r),{mount:w}=i;return i.mount=t=>{const x=Cf(t);if(!x)return;const v=i._component;!at(v)&&!v.render&&!v.template&&(v.template=x.innerHTML),x.nodeType===1&&(x.textContent="");const s=w(x,!1,Mf(x));return x instanceof Element&&(x.removeAttribute("v-cloak"),x.setAttribute("data-v-app","")),s},i},By=(...r)=>{const i=Ny().createApp(...r),{mount:w}=i;return i.mount=t=>{const x=Cf(t);if(x)return w(x,!0,Mf(x))},i};function Mf(r){if(r instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&r instanceof MathMLElement)return"mathml"}function Cf(r){return Ut(r)?document.querySelector(r):r}const Gy=/"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/,Vy=/"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/,Hy=/^\s*["[{]|^\s*-?\d{1,16}(\.\d{1,17})?([Ee][+-]?\d+)?\s*$/;function zy(r,i){if(r==="__proto__"||r==="constructor"&&i&&typeof i=="object"&&"prototype"in i){Wy(r);return}return i}function Wy(r){console.warn(`[destr] Dropping "${r}" key to prevent prototype pollution.`)}function si(r,i={}){if(typeof r!="string")return r;const w=r.trim();if(r[0]==='"'&&r.endsWith('"')&&!r.includes("\\"))return w.slice(1,-1);if(w.length<=9){const t=w.toLowerCase();if(t==="true")return!0;if(t==="false")return!1;if(t==="undefined")return;if(t==="null")return null;if(t==="nan")return Number.NaN;if(t==="infinity")return Number.POSITIVE_INFINITY;if(t==="-infinity")return Number.NEGATIVE_INFINITY}if(!Hy.test(r)){if(i.strict)throw new SyntaxError("[destr] Invalid JSON");return r}try{if(Gy.test(r)||Vy.test(r)){if(i.strict)throw new Error("[destr] Possible prototype pollution");return JSON.parse(r,zy)}return JSON.parse(r)}catch(t){if(i.strict)throw t;return r}}const qy=/#/g,Xy=/&/g,Yy=/\//g,$y=/=/g,Tl=/\+/g,Zy=/%5e/gi,Ky=/%60/gi,Qy=/%7c/gi,Jy=/%20/gi;function eg(r){return encodeURI(""+r).replace(Qy,"|")}function Ia(r){return eg(typeof r=="string"?r:JSON.stringify(r)).replace(Tl,"%2B").replace(Jy,"+").replace(qy,"%23").replace(Xy,"%26").replace(Ky,"`").replace(Zy,"^").replace(Yy,"%2F")}function na(r){return Ia(r).replace($y,"%3D")}function ii(r=""){try{return decodeURIComponent(""+r)}catch{return""+r}}function tg(r){return ii(r.replace(Tl," "))}function rg(r){return ii(r.replace(Tl," "))}function Of(r=""){const i={};r[0]==="?"&&(r=r.slice(1));for(const w of r.split("&")){const t=w.match(/([^=]+)=?(.*)/)||[];if(t.length<2)continue;const x=tg(t[1]);if(x==="__proto__"||x==="constructor")continue;const v=rg(t[2]||"");i[x]===void 0?i[x]=v:Array.isArray(i[x])?i[x].push(v):i[x]=[i[x],v]}return i}function ng(r,i){return(typeof i=="number"||typeof i=="boolean")&&(i=String(i)),i?Array.isArray(i)?i.map(w=>`${na(r)}=${Ia(w)}`).join("&"):`${na(r)}=${Ia(i)}`:na(r)}function og(r){return Object.keys(r).filter(i=>r[i]!==void 0).map(i=>ng(i,r[i])).filter(Boolean).join("&")}const sg=/^[\s\w\0+.-]{2,}:([/\\]{1,2})/,ig=/^[\s\w\0+.-]{2,}:([/\\]{2})?/,ag=/^([/\\]\s*){2,}[^/\\]/,lg=/^[\s\0]*(blob|data|javascript|vbscript):$/i,ug=/\/$|\/\?|\/#/,cg=/^\.?\//;function jn(r,i={}){return typeof i=="boolean"&&(i={acceptRelative:i}),i.strict?sg.test(r):ig.test(r)||(i.acceptRelative?ag.test(r):!1)}function dg(r){return!!r&&lg.test(r)}function Da(r="",i){return i?ug.test(r):r.endsWith("/")}function ji(r="",i){if(!i)return(Da(r)?r.slice(0,-1):r)||"/";if(!Da(r,!0))return r||"/";let w=r,t="";const x=r.indexOf("#");x>=0&&(w=r.slice(0,x),t=r.slice(x));const[v,...s]=w.split("?");return((v.endsWith("/")?v.slice(0,-1):v)||"/")+(s.length>0?`?${s.join("?")}`:"")+t}function ai(r="",i){if(!i)return r.endsWith("/")?r:r+"/";if(Da(r,!0))return r||"/";let w=r,t="";const x=r.indexOf("#");if(x>=0&&(w=r.slice(0,x),t=r.slice(x),!w))return t;const[v,...s]=w.split("?");return v+"/"+(s.length>0?`?${s.join("?")}`:"")+t}function fg(r=""){return r.startsWith("/")}function fc(r=""){return fg(r)?r:"/"+r}function hg(r,i){if(Af(i)||jn(r))return r;const w=ji(i);return r.startsWith(w)?r:Si(w,r)}function hc(r,i){if(Af(i))return r;const w=ji(i);if(!r.startsWith(w))return r;const t=r.slice(w.length);return t[0]==="/"?t:"/"+t}function Pf(r,i){const w=ws(r),t={...Of(w.search),...i};return w.search=og(t),yg(w)}function Af(r){return!r||r==="/"}function pg(r){return r&&r!=="/"}function Si(r,...i){let w=r||"";for(const t of i.filter(x=>pg(x)))if(w){const x=t.replace(cg,"");w=ai(w)+x}else w=t;return w}function Rf(...r){var s,u,o,f;const i=/\/(?!\/)/,w=r.filter(Boolean),t=[];let x=0;for(const g of w)if(!(!g||g==="/")){for(const[m,n]of g.split(i).entries())if(!(!n||n===".")){if(n===".."){if(t.length===1&&jn(t[0]))continue;t.pop(),x--;continue}if(m===1&&((s=t[t.length-1])!=null&&s.endsWith(":/"))){t[t.length-1]+="/"+n;continue}t.push(n),x++}}let v=t.join("/");return x>=0?(u=w[0])!=null&&u.startsWith("/")&&!v.startsWith("/")?v="/"+v:(o=w[0])!=null&&o.startsWith("./")&&!v.startsWith("./")&&(v="./"+v):v="../".repeat(-1*x)+v,(f=w[w.length-1])!=null&&f.endsWith("/")&&!v.endsWith("/")&&(v+="/"),v}function mg(r,i,w={}){return w.trailingSlash||(r=ai(r),i=ai(i)),w.leadingSlash||(r=fc(r),i=fc(i)),w.encoding||(r=ii(r),i=ii(i)),r===i}const Lf=Symbol.for("ufo:protocolRelative");function ws(r="",i){const w=r.match(/^[\s\0]*(blob:|data:|javascript:|vbscript:)(.*)/i);if(w){const[,m,n=""]=w;return{protocol:m.toLowerCase(),pathname:n,href:m+n,auth:"",host:"",search:"",hash:""}}if(!jn(r,{acceptRelative:!0}))return i?ws(i+r):pc(r);const[,t="",x,v=""]=r.replace(/\\/g,"/").match(/^[\s\0]*([\w+.-]{2,}:)?\/\/([^/@]+@)?(.*)/)||[];let[,s="",u=""]=v.match(/([^#/?]*)(.*)?/)||[];t==="file:"&&(u=u.replace(/\/(?=[A-Za-z]:)/,""));const{pathname:o,search:f,hash:g}=pc(u);return{protocol:t.toLowerCase(),auth:x?x.slice(0,Math.max(0,x.length-1)):"",host:s,pathname:o,search:f,hash:g,[Lf]:!t}}function pc(r=""){const[i="",w="",t=""]=(r.match(/([^#?]*)(\?[^#]*)?(#.*)?/)||[]).splice(1);return{pathname:i,search:w,hash:t}}function yg(r){const i=r.pathname||"",w=r.search?(r.search.startsWith("?")?"":"?")+r.search:"",t=r.hash||"",x=r.auth?r.auth+"@":"",v=r.host||"";return(r.protocol||r[Lf]?(r.protocol||"")+"//":"")+x+v+i+w+t}class gg extends Error{constructor(i,w){super(i,w),this.name="FetchError",w!=null&&w.cause&&!this.cause&&(this.cause=w.cause)}}function vg(r){var o,f,g,m,n;const i=((o=r.error)==null?void 0:o.message)||((f=r.error)==null?void 0:f.toString())||"",w=((g=r.request)==null?void 0:g.method)||((m=r.options)==null?void 0:m.method)||"GET",t=((n=r.request)==null?void 0:n.url)||String(r.request)||"/",x=`[${w}] ${JSON.stringify(t)}`,v=r.response?`${r.response.status} ${r.response.statusText}`:"",s=`${x}: ${v}${i?` ${i}`:""}`,u=new gg(s,r.error?{cause:r.error}:void 0);for(const a of["request","options","response"])Object.defineProperty(u,a,{get(){return r[a]}});for(const[a,l]of[["data","_data"],["status","status"],["statusCode","status"],["statusText","statusText"],["statusMessage","statusText"]])Object.defineProperty(u,a,{get(){return r.response&&r.response[l]}});return u}const bg=new Set(Object.freeze(["PATCH","POST","PUT","DELETE"]));function mc(r="GET"){return bg.has(r.toUpperCase())}function _g(r){if(r===void 0)return!1;const i=typeof r;return i==="string"||i==="number"||i==="boolean"||i===null?!0:i!=="object"?!1:Array.isArray(r)?!0:r.buffer?!1:r.constructor&&r.constructor.name==="Object"||typeof r.toJSON=="function"}const wg=new Set(["image/svg","application/xml","application/xhtml","application/html"]),xg=/^application\/(?:[\w!#$%&*.^`~-]*\+)?json(;.+)?$/i;function jg(r=""){if(!r)return"json";const i=r.split(";").shift()||"";return xg.test(i)?"json":wg.has(i)||i.startsWith("text/")?"text":"blob"}function Sg(r,i,w=globalThis.Headers){const t={...i,...r};if(i!=null&&i.params&&(r!=null&&r.params)&&(t.params={...i==null?void 0:i.params,...r==null?void 0:r.params}),i!=null&&i.query&&(r!=null&&r.query)&&(t.query={...i==null?void 0:i.query,...r==null?void 0:r.query}),i!=null&&i.headers&&(r!=null&&r.headers)){t.headers=new w((i==null?void 0:i.headers)||{});for(const[x,v]of new w((r==null?void 0:r.headers)||{}))t.headers.set(x,v)}return t}const Eg=new Set([408,409,425,429,500,502,503,504]),Tg=new Set([101,204,205,304]);function If(r={}){const{fetch:i=globalThis.fetch,Headers:w=globalThis.Headers,AbortController:t=globalThis.AbortController}=r;async function x(u){const o=u.error&&u.error.name==="AbortError"&&!u.options.timeout||!1;if(u.options.retry!==!1&&!o){let g;typeof u.options.retry=="number"?g=u.options.retry:g=mc(u.options.method)?0:1;const m=u.response&&u.response.status||500;if(g>0&&(Array.isArray(u.options.retryStatusCodes)?u.options.retryStatusCodes.includes(m):Eg.has(m))){const n=u.options.retryDelay||0;return n>0&&await new Promise(a=>setTimeout(a,n)),v(u.request,{...u.options,retry:g-1})}}const f=vg(u);throw Error.captureStackTrace&&Error.captureStackTrace(f,v),f}const v=async function(o,f={}){var a;const g={request:o,options:Sg(f,r.defaults,w),response:void 0,error:void 0};g.options.method=(a=g.options.method)==null?void 0:a.toUpperCase(),g.options.onRequest&&await g.options.onRequest(g),typeof g.request=="string"&&(g.options.baseURL&&(g.request=hg(g.request,g.options.baseURL)),(g.options.query||g.options.params)&&(g.request=Pf(g.request,{...g.options.params,...g.options.query}))),g.options.body&&mc(g.options.method)&&(_g(g.options.body)?(g.options.body=typeof g.options.body=="string"?g.options.body:JSON.stringify(g.options.body),g.options.headers=new w(g.options.headers||{}),g.options.headers.has("content-type")||g.options.headers.set("content-type","application/json"),g.options.headers.has("accept")||g.options.headers.set("accept","application/json")):("pipeTo"in g.options.body&&typeof g.options.body.pipeTo=="function"||typeof g.options.body.pipe=="function")&&("duplex"in g.options||(g.options.duplex="half")));let m;if(!g.options.signal&&g.options.timeout){const l=new t;m=setTimeout(()=>l.abort(),g.options.timeout),g.options.signal=l.signal}try{g.response=await i(g.request,g.options)}catch(l){return g.error=l,g.options.onRequestError&&await g.options.onRequestError(g),await x(g)}finally{m&&clearTimeout(m)}if(g.response.body&&!Tg.has(g.response.status)&&g.options.method!=="HEAD"){const l=(g.options.parseResponse?"json":g.options.responseType)||jg(g.response.headers.get("content-type")||"");switch(l){case"json":{const d=await g.response.text(),y=g.options.parseResponse||si;g.response._data=y(d);break}case"stream":{g.response._data=g.response.body;break}default:g.response._data=await g.response[l]()}}return g.options.onResponse&&await g.options.onResponse(g),!g.options.ignoreResponseError&&g.response.status>=400&&g.response.status<600?(g.options.onResponseError&&await g.options.onResponseError(g),await x(g)):g.response},s=async function(o,f){return(await v(o,f))._data};return s.raw=v,s.native=(...u)=>i(...u),s.create=(u={})=>If({...r,defaults:{...r.defaults,...u}}),s}const kl=function(){if(typeof globalThis<"u")return globalThis;if(typeof self<"u")return self;if(typeof window<"u")return window;if(typeof global<"u")return global;throw new Error("unable to locate global object")}(),kg=kl.fetch||(()=>Promise.reject(new Error("[ofetch] global.fetch is not supported!"))),Mg=kl.Headers,Cg=kl.AbortController,Og=If({fetch:kg,Headers:Mg,AbortController:Cg}),Pg=Og,Ag=()=>{var r;return((r=window==null?void 0:window.__NUXT__)==null?void 0:r.config)||{}},li=Ag().app,Rg=()=>li.baseURL,Lg=()=>li.buildAssetsDir,Ml=(...r)=>Rf(Df(),Lg(),...r),Df=(...r)=>{const i=li.cdnURL||li.baseURL;return r.length?Rf(i,...r):i};globalThis.__buildAssetsURL=Ml,globalThis.__publicAssetsURL=Df;globalThis.$fetch||(globalThis.$fetch=Pg.create({baseURL:Rg()}));function Fa(r,i={},w){for(const t in r){const x=r[t],v=w?`${w}:${t}`:t;typeof x=="object"&&x!==null?Fa(x,i,v):typeof x=="function"&&(i[v]=x)}return i}const Ig={run:r=>r()},Dg=()=>Ig,Ff=typeof console.createTask<"u"?console.createTask:Dg;function Fg(r,i){const w=i.shift(),t=Ff(w);return r.reduce((x,v)=>x.then(()=>t.run(()=>v(...i))),Promise.resolve())}function Ng(r,i){const w=i.shift(),t=Ff(w);return Promise.all(r.map(x=>t.run(()=>x(...i))))}function oa(r,i){for(const w of[...r])w(i)}class Ug{constructor(){this._hooks={},this._before=void 0,this._after=void 0,this._deprecatedMessages=void 0,this._deprecatedHooks={},this.hook=this.hook.bind(this),this.callHook=this.callHook.bind(this),this.callHookWith=this.callHookWith.bind(this)}hook(i,w,t={}){if(!i||typeof w!="function")return()=>{};const x=i;let v;for(;this._deprecatedHooks[i];)v=this._deprecatedHooks[i],i=v.to;if(v&&!t.allowDeprecated){let s=v.message;s||(s=`${x} hook has been deprecated`+(v.to?`, please use ${v.to}`:"")),this._deprecatedMessages||(this._deprecatedMessages=new Set),this._deprecatedMessages.has(s)||(console.warn(s),this._deprecatedMessages.add(s))}if(!w.name)try{Object.defineProperty(w,"name",{get:()=>"_"+i.replace(/\W+/g,"_")+"_hook_cb",configurable:!0})}catch{}return this._hooks[i]=this._hooks[i]||[],this._hooks[i].push(w),()=>{w&&(this.removeHook(i,w),w=void 0)}}hookOnce(i,w){let t,x=(...v)=>(typeof t=="function"&&t(),t=void 0,x=void 0,w(...v));return t=this.hook(i,x),t}removeHook(i,w){if(this._hooks[i]){const t=this._hooks[i].indexOf(w);t!==-1&&this._hooks[i].splice(t,1),this._hooks[i].length===0&&delete this._hooks[i]}}deprecateHook(i,w){this._deprecatedHooks[i]=typeof w=="string"?{to:w}:w;const t=this._hooks[i]||[];delete this._hooks[i];for(const x of t)this.hook(i,x)}deprecateHooks(i){Object.assign(this._deprecatedHooks,i);for(const w in i)this.deprecateHook(w,i[w])}addHooks(i){const w=Fa(i),t=Object.keys(w).map(x=>this.hook(x,w[x]));return()=>{for(const x of t.splice(0,t.length))x()}}removeHooks(i){const w=Fa(i);for(const t in w)this.removeHook(t,w[t])}removeAllHooks(){for(const i in this._hooks)delete this._hooks[i]}callHook(i,...w){return w.unshift(i),this.callHookWith(Fg,i,...w)}callHookParallel(i,...w){return w.unshift(i),this.callHookWith(Ng,i,...w)}callHookWith(i,w,...t){const x=this._before||this._after?{name:w,args:t,context:{}}:void 0;this._before&&oa(this._before,x);const v=i(w in this._hooks?[...this._hooks[w]]:[],t);return v instanceof Promise?v.finally(()=>{this._after&&x&&oa(this._after,x)}):(this._after&&x&&oa(this._after,x),v)}beforeEach(i){return this._before=this._before||[],this._before.push(i),()=>{if(this._before!==void 0){const w=this._before.indexOf(i);w!==-1&&this._before.splice(w,1)}}}afterEach(i){return this._after=this._after||[],this._after.push(i),()=>{if(this._after!==void 0){const w=this._after.indexOf(i);w!==-1&&this._after.splice(w,1)}}}}function Nf(){return new Ug}function Bg(r={}){let i,w=!1;const t=s=>{if(i&&i!==s)throw new Error("Context conflict")};let x;if(r.asyncContext){const s=r.AsyncLocalStorage||globalThis.AsyncLocalStorage;s?x=new s:console.warn("[unctx] `AsyncLocalStorage` is not provided.")}const v=()=>{if(x&&i===void 0){const s=x.getStore();if(s!==void 0)return s}return i};return{use:()=>{const s=v();if(s===void 0)throw new Error("Context is not available");return s},tryUse:()=>v(),set:(s,u)=>{u||t(s),i=s,w=!0},unset:()=>{i=void 0,w=!1},call:(s,u)=>{t(s),i=s;try{return x?x.run(s,u):u()}finally{w||(i=void 0)}},async callAsync(s,u){i=s;const o=()=>{i=s},f=()=>i===s?o:void 0;Na.add(f);try{const g=x?x.run(s,u):u();return w||(i=void 0),await g}finally{Na.delete(f)}}}}function Gg(r={}){const i={};return{get(w,t={}){return i[w]||(i[w]=Bg({...r,...t})),i[w],i[w]}}}const ui=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof global<"u"?global:typeof window<"u"?window:{},yc="__unctx__",Vg=ui[yc]||(ui[yc]=Gg()),Hg=(r,i={})=>Vg.get(r,i),gc="__unctx_async_handlers__",Na=ui[gc]||(ui[gc]=new Set);function us(r){const i=[];for(const x of Na){const v=x();v&&i.push(v)}const w=()=>{for(const x of i)x()};let t=r();return t&&typeof t=="object"&&"catch"in t&&(t=t.catch(x=>{throw w(),x})),[t,w]}const Uf=Hg("nuxt-app",{asyncContext:!1}),zg="__nuxt_plugin";function Wg(r){let i=0;const w={_scope:bp(),provide:void 0,globalName:"nuxt",versions:{get nuxt(){return"3.11.2"},get vue(){return w.vueApp.version}},payload:qn({data:{},state:{},once:new Set,_errors:{},...window.__NUXT__??{}}),static:{data:{}},runWithContext:x=>w._scope.run(()=>Yg(w,x)),isHydrating:!0,deferHydration(){if(!w.isHydrating)return()=>{};i++;let x=!1;return()=>{if(!x&&(x=!0,i--,i===0))return w.isHydrating=!1,w.callHook("app:suspense:resolve")}},_asyncDataPromises:{},_asyncData:{},_payloadRevivers:{},...r};w.hooks=Nf(),w.hook=w.hooks.hook,w.callHook=w.hooks.callHook,w.provide=(x,v)=>{const s="$"+x;Us(w,s,v),Us(w.vueApp.config.globalProperties,s,v)},Us(w.vueApp,"$nuxt",w),Us(w.vueApp.config.globalProperties,"$nuxt",w);{window.addEventListener("nuxt.preloadError",v=>{w.callHook("app:chunkError",{error:v.payload})}),window.useNuxtApp=window.useNuxtApp||Dt;const x=w.hook("app:error",(...v)=>{console.error("[nuxt] error caught during app initialization",...v)});w.hook("app:mounted",x)}const t=w.payload.config;return w.provide("config",t),w}async function qg(r,i){if(i.hooks&&r.hooks.addHooks(i.hooks),typeof i=="function"){const{provide:w}=await r.runWithContext(()=>i(r))||{};if(w&&typeof w=="object")for(const t in w)r.provide(t,w[t])}}async function Xg(r,i){const w=[],t=[],x=[],v=[];let s=0;async function u(o){var g;const f=((g=o.dependsOn)==null?void 0:g.filter(m=>i.some(n=>n._name===m)&&!w.includes(m)))??[];if(f.length>0)t.push([new Set(f),o]);else{const m=qg(r,o).then(async()=>{o._name&&(w.push(o._name),await Promise.all(t.map(async([n,a])=>{n.has(o._name)&&(n.delete(o._name),n.size===0&&(s++,await u(a)))})))});o.parallel?x.push(m.catch(n=>v.push(n))):await m}}for(const o of i)await u(o);if(await Promise.all(x),s)for(let o=0;o{}),r,{[zg]:!0,_name:i})}function Yg(r,i,w){const t=()=>i();return Uf.set(r),r.vueApp.runWithContext(t)}function $g(){var i;let r;return Qd()&&(r=(i=ao())==null?void 0:i.appContext.app.$nuxt),r=r||Uf.tryUse(),r||null}function Dt(){const r=$g();if(!r)throw new Error("[nuxt] instance unavailable");return r}function Ei(r){return Dt().$config}function Us(r,i,w){Object.defineProperty(r,i,{get:()=>w})}function Zg(r,i){return{ctx:{table:r},matchAll:w=>Gf(w,r)}}function Bf(r){const i={};for(const w in r)i[w]=w==="dynamic"?new Map(Object.entries(r[w]).map(([t,x])=>[t,Bf(x)])):new Map(Object.entries(r[w]));return i}function Kg(r){return Zg(Bf(r))}function Gf(r,i,w){r.endsWith("/")&&(r=r.slice(0,-1)||"/");const t=[];for(const[v,s]of vc(i.wildcard))(r===v||r.startsWith(v+"/"))&&t.push(s);for(const[v,s]of vc(i.dynamic))if(r.startsWith(v+"/")){const u="/"+r.slice(v.length).split("/").splice(2).join("/");t.push(...Gf(u,s))}const x=i.static.get(r);return x&&t.push(x),t.filter(Boolean)}function vc(r){return[...r.entries()].sort((i,w)=>i[0].length-w[0].length)}function sa(r){if(r===null||typeof r!="object")return!1;const i=Object.getPrototypeOf(r);return i!==null&&i!==Object.prototype&&Object.getPrototypeOf(i)!==null||Symbol.iterator in r?!1:Symbol.toStringTag in r?Object.prototype.toString.call(r)==="[object Module]":!0}function Ua(r,i,w=".",t){if(!sa(i))return Ua(r,{},w,t);const x=Object.assign({},i);for(const v in r){if(v==="__proto__"||v==="constructor")continue;const s=r[v];s!=null&&(t&&t(x,v,s,w)||(Array.isArray(s)&&Array.isArray(x[v])?x[v]=[...s,...x[v]]:sa(s)&&sa(x[v])?x[v]=Ua(s,x[v],(w?`${w}.`:"")+v.toString(),t):x[v]=s))}return x}function Vf(r){return(...i)=>i.reduce((w,t)=>Ua(w,t,"",r),{})}const Hf=Vf(),Qg=Vf((r,i,w)=>{if(r[i]!==void 0&&typeof w=="function")return r[i]=w(r[i]),!0});function Jg(r,i){try{return i in r}catch{return!1}}var ev=Object.defineProperty,tv=(r,i,w)=>i in r?ev(r,i,{enumerable:!0,configurable:!0,writable:!0,value:w}):r[i]=w,Qn=(r,i,w)=>(tv(r,typeof i!="symbol"?i+"":i,w),w);class Ba extends Error{constructor(i,w={}){super(i,w),Qn(this,"statusCode",500),Qn(this,"fatal",!1),Qn(this,"unhandled",!1),Qn(this,"statusMessage"),Qn(this,"data"),Qn(this,"cause"),w.cause&&!this.cause&&(this.cause=w.cause)}toJSON(){const i={message:this.message,statusCode:Va(this.statusCode,500)};return this.statusMessage&&(i.statusMessage=zf(this.statusMessage)),this.data!==void 0&&(i.data=this.data),i}}Qn(Ba,"__h3_error__",!0);function Ga(r){if(typeof r=="string")return new Ba(r);if(rv(r))return r;const i=new Ba(r.message??r.statusMessage??"",{cause:r.cause||r});if(Jg(r,"stack"))try{Object.defineProperty(i,"stack",{get(){return r.stack}})}catch{try{i.stack=r.stack}catch{}}if(r.data&&(i.data=r.data),r.statusCode?i.statusCode=Va(r.statusCode,i.statusCode):r.status&&(i.statusCode=Va(r.status,i.statusCode)),r.statusMessage?i.statusMessage=r.statusMessage:r.statusText&&(i.statusMessage=r.statusText),i.statusMessage){const w=i.statusMessage;zf(i.statusMessage)!==w&&console.warn("[h3] Please prefer using `message` for longer error messages instead of `statusMessage`. In the future, `statusMessage` will be sanitized by default.")}return r.fatal!==void 0&&(i.fatal=r.fatal),r.unhandled!==void 0&&(i.unhandled=r.unhandled),i}function rv(r){var i;return((i=r==null?void 0:r.constructor)==null?void 0:i.__h3_error__)===!0}const nv=/[^\u0009\u0020-\u007E]/g;function zf(r=""){return r.replace(nv,"")}function Va(r,i=200){return!r||(typeof r=="string"&&(r=Number.parseInt(r,10)),r<100||r>999)?i:r}const Wf=Symbol("layout-meta"),xs=Symbol("route"),Xr=()=>{var r;return(r=Dt())==null?void 0:r.$router},Ti=()=>Qd()?zt(xs,Dt()._route):Dt()._route;const ov=()=>{try{if(Dt()._processingMiddleware)return!0}catch{return!1}return!1},sv=(r,i)=>{r||(r="/");const w=typeof r=="string"?r:Pf(r.path||"/",r.query||{})+(r.hash||"");if(i!=null&&i.open){const{target:u="_blank",windowFeatures:o={}}=i.open,f=Object.entries(o).filter(([g,m])=>m!==void 0).map(([g,m])=>`${g.toLowerCase()}=${m}`).join(", ");return open(w,u,f),Promise.resolve()}const t=(i==null?void 0:i.external)||jn(w,{acceptRelative:!0});if(t){if(!(i!=null&&i.external))throw new Error("Navigating to an external URL is not allowed by default. Use `navigateTo(url, { external: true })`.");const u=ws(w).protocol;if(u&&dg(u))throw new Error(`Cannot navigate to a URL with '${u}' protocol.`)}const x=ov();if(!t&&x)return r;const v=Xr(),s=Dt();return t?(s._scope.stop(),i!=null&&i.replace?location.replace(w):location.href=w,x?s.isHydrating?new Promise(()=>{}):!1:Promise.resolve()):i!=null&&i.replace?v.replace(r):v.push(r)},qf="__nuxt_error",ki=()=>Yp(Dt().payload,"error"),bo=r=>{const i=Mi(r);try{const w=Dt(),t=ki();w.hooks.callHook("app:error",i),t.value=t.value||i}catch{throw i}return i},iv=async(r={})=>{const i=Dt(),w=ki();i.callHook("app:error:cleared",r),r.redirect&&await Xr().replace(r.redirect),w.value=null},av=r=>!!r&&typeof r=="object"&&qf in r,Mi=r=>{const i=Ga(r);return Object.defineProperty(i,qf,{value:!0,configurable:!1,writable:!1}),i},lv=-1,uv=-2,cv=-3,dv=-4,fv=-5,hv=-6;function pv(r,i){return mv(JSON.parse(r),i)}function mv(r,i){if(typeof r=="number")return x(r,!0);if(!Array.isArray(r)||r.length===0)throw new Error("Invalid input");const w=r,t=Array(w.length);function x(v,s=!1){if(v===lv)return;if(v===cv)return NaN;if(v===dv)return 1/0;if(v===fv)return-1/0;if(v===hv)return-0;if(s)throw new Error("Invalid input");if(v in t)return t[v];const u=w[v];if(!u||typeof u!="object")t[v]=u;else if(Array.isArray(u))if(typeof u[0]=="string"){const o=u[0],f=i==null?void 0:i[o];if(f)return t[v]=f(x(u[1]));switch(o){case"Date":t[v]=new Date(u[1]);break;case"Set":const g=new Set;t[v]=g;for(let a=1;a>>9)+65536).toString(16).substring(1,8).toLowerCase()}function Ha(r){if(r._h)return r._h;if(r._d)return ci(r._d);let i=`${r.tag}:${r.textContent||r.innerHTML||""}:`;for(const w in r.props)i+=`${w}:${String(r.props[w])},`;return ci(i)}function Yf(r,i){const w=[],t=i.resolveKeyData||(v=>v.key),x=i.resolveValueData||(v=>v.value);for(const[v,s]of Object.entries(r))w.push(...(Array.isArray(s)?s:[s]).map(u=>{const o={key:v,value:u},f=x(o);return typeof f=="object"?Yf(f,i):Array.isArray(f)?f:{[typeof i.key=="function"?i.key(o):i.key]:t(o),[typeof i.value=="function"?i.value(o):i.value]:f}}).flat());return w}function $f(r,i){return Object.entries(r).map(([w,t])=>{if(typeof t=="object"&&(t=$f(t,i)),i.resolve){const x=i.resolve({key:w,value:t});if(typeof x<"u")return x}return typeof t=="number"&&(t=t.toString()),typeof t=="string"&&i.wrapValue&&(t=t.replace(new RegExp(i.wrapValue,"g"),`\\${i.wrapValue}`),t=`${i.wrapValue}${t}${i.wrapValue}`),`${w}${i.keyValueSeparator||""}${t}`}).join(i.entrySeparator||"")}const vr=r=>({keyValue:r,metaKey:"property"}),ia=r=>({keyValue:r}),Cl={appleItunesApp:{unpack:{entrySeparator:", ",resolve({key:r,value:i}){return`${_n(r)}=${i}`}}},articleExpirationTime:vr("article:expiration_time"),articleModifiedTime:vr("article:modified_time"),articlePublishedTime:vr("article:published_time"),bookReleaseDate:vr("book:release_date"),charset:{metaKey:"charset"},contentSecurityPolicy:{unpack:{entrySeparator:"; ",resolve({key:r,value:i}){return`${_n(r)} ${i}`}},metaKey:"http-equiv"},contentType:{metaKey:"http-equiv"},defaultStyle:{metaKey:"http-equiv"},fbAppId:vr("fb:app_id"),msapplicationConfig:ia("msapplication-Config"),msapplicationTileColor:ia("msapplication-TileColor"),msapplicationTileImage:ia("msapplication-TileImage"),ogAudioSecureUrl:vr("og:audio:secure_url"),ogAudioUrl:vr("og:audio"),ogImageSecureUrl:vr("og:image:secure_url"),ogImageUrl:vr("og:image"),ogSiteName:vr("og:site_name"),ogVideoSecureUrl:vr("og:video:secure_url"),ogVideoUrl:vr("og:video"),profileFirstName:vr("profile:first_name"),profileLastName:vr("profile:last_name"),profileUsername:vr("profile:username"),refresh:{metaKey:"http-equiv",unpack:{entrySeparator:";",resolve({key:r,value:i}){if(r==="seconds")return`${i}`}}},robots:{unpack:{entrySeparator:", ",resolve({key:r,value:i}){return typeof i=="boolean"?`${_n(r)}`:`${_n(r)}:${i}`}}},xUaCompatible:{metaKey:"http-equiv"}},Zf=new Set(["og","book","article","profile"]);function Kf(r){var t;const i=_n(r),w=i.indexOf(":");return Zf.has(i.substring(0,w))?"property":((t=Cl[r])==null?void 0:t.metaKey)||"name"}function _v(r){var i;return((i=Cl[r])==null?void 0:i.keyValue)||_n(r)}function _n(r){const i=r.replace(/([A-Z])/g,"-$1").toLowerCase(),w=i.indexOf("-"),t=i.substring(0,w);return t==="twitter"||Zf.has(t)?r.replace(/([A-Z])/g,":$1").toLowerCase():i}function za(r){if(Array.isArray(r))return r.map(w=>za(w));if(typeof r!="object"||Array.isArray(r))return r;const i={};for(const w in r)Object.prototype.hasOwnProperty.call(r,w)&&(i[_n(w)]=za(r[w]));return i}function wv(r,i){const w=Cl[i];return i==="refresh"?`${r.seconds};url=${r.url}`:$f(za(r),{keyValueSeparator:"=",entrySeparator:", ",resolve({value:t,key:x}){if(t===null)return"";if(typeof t=="boolean")return`${x}`},...w==null?void 0:w.unpack})}const Qf=new Set(["og:image","og:video","og:audio","twitter:image"]);function Jf(r){const i={};for(const w in r){if(!Object.prototype.hasOwnProperty.call(r,w))continue;const t=r[w];String(t)!=="false"&&w&&(i[w]=t)}return i}function bc(r,i){const w=Jf(i),t=_n(r),x=Kf(t);if(Qf.has(t)){const v={};for(const s in w)Object.prototype.hasOwnProperty.call(w,s)&&(v[`${r}${s==="url"?"":`${s[0].toUpperCase()}${s.slice(1)}`}`]=w[s]);return Ol(v).sort((s,u)=>{var o,f;return(((o=s[x])==null?void 0:o.length)||0)-(((f=u[x])==null?void 0:f.length)||0)})}return[{[x]:t,...w}]}function Ol(r){const i=[],w={};for(const x in r){if(!Object.prototype.hasOwnProperty.call(r,x))continue;const v=r[x];if(!Array.isArray(v)){if(typeof v=="object"&&v){if(Qf.has(_n(x))){i.push(...bc(x,v));continue}w[x]=Jf(v)}else w[x]=v;continue}for(const s of v)i.push(...typeof s=="string"?Ol({[x]:s}):bc(x,s))}const t=Yf(w,{key({key:x}){return Kf(x)},value({key:x}){return x==="charset"?"charset":"content"},resolveKeyData({key:x}){return _v(x)},resolveValueData({value:x,key:v}){return x===null?"_null":typeof x=="object"?wv(x,v):typeof x=="number"?x.toString():x}});return[...i,...t].map(x=>(x.content==="_null"&&(x.content=null),x))}function xv(r,i){return r instanceof Promise?r.then(i):i(r)}function Wa(r,i,w,t){const x=t||th(typeof i=="object"&&typeof i!="function"&&!(i instanceof Promise)?{...i}:{[r==="script"||r==="noscript"||r==="style"?"innerHTML":"textContent"]:i},r==="templateParams"||r==="titleTemplate");if(x instanceof Promise)return x.then(s=>Wa(r,i,w,s));const v={tag:r,props:x};for(const s of Xf){const u=v.props[s]!==void 0?v.props[s]:w[s];u!==void 0&&((!(s==="innerHTML"||s==="textContent"||s==="children")||yv.has(v.tag))&&(v[s==="children"?"innerHTML":s]=u),delete v.props[s])}return v.props.body&&(v.tagPosition="bodyClose",delete v.props.body),v.tag==="script"&&typeof v.innerHTML=="object"&&(v.innerHTML=JSON.stringify(v.innerHTML),v.props.type=v.props.type||"application/json"),Array.isArray(v.props.content)?v.props.content.map(s=>({...v,props:{...v.props,content:s}})):v}function jv(r,i){var t;const w=r==="class"?" ":";";return i&&typeof i=="object"&&!Array.isArray(i)&&(i=Object.entries(i).filter(([,x])=>x).map(([x,v])=>r==="style"?`${x}:${v}`:x)),(t=String(Array.isArray(i)?i.join(w):i))==null?void 0:t.split(w).filter(x=>!!x.trim()).join(w)}function eh(r,i,w,t){for(let x=t;x(r[v]=s,eh(r,i,w,x)));if(!i&&!Xf.has(v)){const s=String(r[v]),u=v.startsWith("data-");s==="true"||s===""?r[v]=u?"true":!0:r[v]||(u&&s==="false"?r[v]="false":delete r[v])}}}function th(r,i=!1){const w=eh(r,i,Object.keys(r),0);return w instanceof Promise?w.then(()=>r):r}const Sv=10;function rh(r,i,w){for(let t=w;t(i[t]=v,rh(r,i,t)));Array.isArray(x)?r.push(...x):r.push(x)}}function Ev(r){const i=[],w=r.resolvedInput;for(const x in w){if(!Object.prototype.hasOwnProperty.call(w,x))continue;const v=w[x];if(!(v===void 0||!gv.has(x))){if(Array.isArray(v)){for(const s of v)i.push(Wa(x,s,r));continue}i.push(Wa(x,v,r))}}if(i.length===0)return[];const t=[];return xv(rh(t,i,0),()=>t.map((x,v)=>(x._e=r._i,r.mode&&(x._m=r.mode),x._p=(r._i<{if(s===Ln||!x.includes(s))return s;const u=Mv(i,s.slice(1));return u!==void 0?u:s}).trim(),v&&(r.endsWith(Ln)&&(r=r.slice(0,-Ln.length)),r.startsWith(Ln)&&(r=r.slice(Ln.length)),r=r.replace(Cv,w).trim()),r}function jc(r,i){return r==null?i||null:typeof r=="function"?r(i):r}async function oh(r,i={}){const w=i.document||r.resolvedOptions.document;if(!w||!r.dirty)return;const t={shouldRender:!0,tags:[]};if(await r.hooks.callHook("dom:beforeRender",t),!!t.shouldRender)return r._domUpdatePromise||(r._domUpdatePromise=new Promise(async x=>{var m;const v=(await r.resolveTags()).map(n=>({tag:n,id:Ys.has(n.tag)?Ha(n):n.tag,shouldRender:!0}));let s=r._dom;if(!s){s={elMap:{htmlAttrs:w.documentElement,bodyAttrs:w.body}};const n=new Set;for(const a of["body","head"]){const l=(m=w[a])==null?void 0:m.children;for(const d of l){const y=d.tagName.toLowerCase();if(!Ys.has(y))continue;const h={tag:y,props:await th(d.getAttributeNames().reduce((j,M)=>({...j,[M]:d.getAttribute(M)}),{})),innerHTML:d.innerHTML},c=nh(h);let p=c,b=1;for(;p&&n.has(p);)p=`${c}:${b++}`;p&&(h._d=p,n.add(p)),s.elMap[d.getAttribute("data-hid")||Ha(h)]=d}}}s.pendingSideEffects={...s.sideEffects},s.sideEffects={};function u(n,a,l){const d=`${n}:${a}`;s.sideEffects[d]=l,delete s.pendingSideEffects[d]}function o({id:n,$el:a,tag:l}){const d=l.tag.endsWith("Attrs");if(s.elMap[n]=a,d||(l.textContent&&l.textContent!==a.textContent&&(a.textContent=l.textContent),l.innerHTML&&l.innerHTML!==a.innerHTML&&(a.innerHTML=l.innerHTML),u(n,"el",()=>{var y;(y=s.elMap[n])==null||y.remove(),delete s.elMap[n]})),l._eventHandlers)for(const y in l._eventHandlers)Object.prototype.hasOwnProperty.call(l._eventHandlers,y)&&a.getAttribute(`data-${y}`)!==""&&((l.tag==="bodyAttrs"?w.defaultView:a).addEventListener(y.substring(2),l._eventHandlers[y].bind(a)),a.setAttribute(`data-${y}`,""));for(const y in l.props){if(!Object.prototype.hasOwnProperty.call(l.props,y))continue;const h=l.props[y],c=`attr:${y}`;if(y==="class"){if(!h)continue;for(const p of h.split(" "))d&&u(n,`${c}:${p}`,()=>a.classList.remove(p)),!a.classList.contains(p)&&a.classList.add(p)}else if(y==="style"){if(!h)continue;for(const p of h.split(";")){const b=p.indexOf(":"),j=p.substring(0,b).trim(),M=p.substring(b+1).trim();u(n,`${c}:${j}`,()=>{a.style.removeProperty(j)}),a.style.setProperty(j,M)}}else a.getAttribute(y)!==h&&a.setAttribute(y,h===!0?"":String(h)),d&&u(n,c,()=>a.removeAttribute(y))}}const f=[],g={bodyClose:void 0,bodyOpen:void 0,head:void 0};for(const n of v){const{tag:a,shouldRender:l,id:d}=n;if(l){if(a.tag==="title"){w.title=a.textContent;continue}n.$el=n.$el||s.elMap[d],n.$el?o(n):Ys.has(a.tag)&&f.push(n)}}for(const n of f){const a=n.tag.tagPosition||"head";n.$el=w.createElement(n.tag.tag),o(n),g[a]=g[a]||w.createDocumentFragment(),g[a].appendChild(n.$el)}for(const n of v)await r.hooks.callHook("dom:renderTag",n,w,u);g.head&&w.head.appendChild(g.head),g.bodyOpen&&w.body.insertBefore(g.bodyOpen,w.body.firstChild),g.bodyClose&&w.body.appendChild(g.bodyClose);for(const n in s.pendingSideEffects)s.pendingSideEffects[n]();r._dom=s,await r.hooks.callHook("dom:rendered",{renders:v}),x()}).finally(()=>{r._domUpdatePromise=void 0,r.dirty=!1})),r._domUpdatePromise}function Ov(r,i={}){const w=i.delayFn||(t=>setTimeout(t,10));return r._domDebouncedUpdatePromise=r._domDebouncedUpdatePromise||new Promise(t=>w(()=>oh(r,i).then(()=>{delete r._domDebouncedUpdatePromise,t()})))}function Pv(r){return i=>{var t,x;const w=((x=(t=i.resolvedOptions.document)==null?void 0:t.head.querySelector('script[id="unhead:payload"]'))==null?void 0:x.innerHTML)||!1;return w&&i.push(JSON.parse(w)),{mode:"client",hooks:{"entries:updated":v=>{Ov(v,r)}}}}}const Av=new Set(["templateParams","htmlAttrs","bodyAttrs"]),Rv={hooks:{"tag:normalise":({tag:r})=>{r.props.hid&&(r.key=r.props.hid,delete r.props.hid),r.props.vmid&&(r.key=r.props.vmid,delete r.props.vmid),r.props.key&&(r.key=r.props.key,delete r.props.key);const i=nh(r);i&&!i.startsWith("meta:og:")&&!i.startsWith("meta:twitter:")&&delete r.key;const w=i||(r.key?`${r.tag}:${r.key}`:!1);w&&(r._d=w)},"tags:resolve":r=>{const i=Object.create(null);for(const t of r.tags){const x=(t.key?`${t.tag}:${t.key}`:t._d)||Ha(t),v=i[x];if(v){let u=t==null?void 0:t.tagDuplicateStrategy;if(!u&&Av.has(t.tag)&&(u="merge"),u==="merge"){const o=v.props;o.style&&t.props.style&&(o.style[o.style.length-1]!==";"&&(o.style+=";"),t.props.style=`${o.style} ${t.props.style}`),o.class&&t.props.class?t.props.class=`${o.class} ${t.props.class}`:o.class&&(t.props.class=o.class),i[x].props={...o,...t.props};continue}else if(t._e===v._e){v._duped=v._duped||[],t._d=`${v._d}:${v._duped.length+1}`,v._duped.push(t);continue}else if(di(t)>di(v))continue}if(!(t.innerHTML||t.textContent||Object.keys(t.props).length!==0)&&Ys.has(t.tag)){delete i[x];continue}i[x]=t}const w=[];for(const t in i){const x=i[t],v=x._duped;w.push(x),v&&(delete x._duped,w.push(...v))}r.tags=w,r.tags=r.tags.filter(t=>!(t.tag==="meta"&&(t.props.name||t.props.property)&&!t.props.content))}}},Lv=new Set(["script","link","bodyAttrs"]),Iv=r=>({hooks:{"tags:resolve":i=>{for(const w of i.tags){if(!Lv.has(w.tag))continue;const t=w.props;for(const x in t){if(x[0]!=="o"||x[1]!=="n"||!Object.prototype.hasOwnProperty.call(t,x))continue;const v=t[x];typeof v=="function"&&(r.ssr&&_c.has(x)?t[x]=`this.dataset.${x}fired = true`:delete t[x],w._eventHandlers=w._eventHandlers||{},w._eventHandlers[x]=v)}r.ssr&&w._eventHandlers&&(w.props.src||w.props.href)&&(w.key=w.key||ci(w.props.src||w.props.href))}},"dom:renderTag":({$el:i,tag:w})=>{var x,v;const t=i==null?void 0:i.dataset;if(t)for(const s in t){if(!s.endsWith("fired"))continue;const u=s.slice(0,-5);_c.has(u)&&((v=(x=w._eventHandlers)==null?void 0:x[u])==null||v.call(i,new Event(u.substring(2))))}}}}),Dv=new Set(["link","style","script","noscript"]),Fv={hooks:{"tag:normalise":({tag:r})=>{r.key&&Dv.has(r.tag)&&(r.props["data-hid"]=r._h=ci(r.key))}}},Nv={mode:"server",hooks:{"tags:beforeResolve":r=>{const i={};let w=!1;for(const t of r.tags)t._m!=="server"||t.tag!=="titleTemplate"&&t.tag!=="templateParams"&&t.tag!=="title"||(i[t.tag]=t.tag==="title"||t.tag==="titleTemplate"?t.textContent:t.props,w=!0);w&&r.tags.push({tag:"script",innerHTML:JSON.stringify(i),props:{id:"unhead:payload",type:"application/json"}})}}},Uv={hooks:{"tags:resolve":r=>{var i;for(const w of r.tags)if(typeof w.tagPriority=="string")for(const{prefix:t,offset:x}of Tv){if(!w.tagPriority.startsWith(t))continue;const v=w.tagPriority.substring(t.length),s=(i=r.tags.find(u=>u._d===v))==null?void 0:i._p;if(s!==void 0){w._p=s+x;break}}r.tags.sort((w,t)=>{const x=di(w),v=di(t);return xv?1:w._p-t._p})}}},Bv={meta:"content",link:"href",htmlAttrs:"lang"},Gv=["innerHTML","textContent"],Vv=r=>({hooks:{"tags:resolve":i=>{var s;const{tags:w}=i;let t;for(let u=0;uu.tag==="title"))==null?void 0:s.textContent)||"",x,v);for(const u of w){if(u.processTemplateParams===!1)continue;const o=Bv[u.tag];if(o&&typeof u.props[o]=="string")u.props[o]=Bs(u.props[o],x,v);else if(u.processTemplateParams||u.tag==="titleTemplate"||u.tag==="title")for(const f of Gv)typeof u[f]=="string"&&(u[f]=Bs(u[f],x,v))}r._templateParams=x,r._separator=v},"tags:afterResolve":({tags:i})=>{let w;for(let t=0;t{const{tags:i}=r;let w,t;for(let x=0;x{for(const i of r.tags)typeof i.innerHTML=="string"&&(i.innerHTML&&(i.props.type==="application/ld+json"||i.props.type==="application/json")?i.innerHTML=i.innerHTML.replace(/{u.dirty=!0,i.callHook("entries:updated",u)};let x=0,v=[];const s=[],u={plugins:s,dirty:!1,resolvedOptions:r,hooks:i,headEntries(){return v},use(o){const f=typeof o=="function"?o(u):o;(!f.key||!s.some(g=>g.key===f.key))&&(s.push(f),Sc(f.mode,w)&&i.addHooks(f.hooks||{}))},push(o,f){f==null||delete f.head;const g={_i:x++,input:o,...f};return Sc(g.mode,w)&&(v.push(g),t()),{dispose(){v=v.filter(m=>m._i!==g._i),t()},patch(m){for(const n of v)n._i===g._i&&(n.input=g.input=m);t()}}},async resolveTags(){const o={tags:[],entries:[...v]};await i.callHook("entries:resolve",o);for(const f of o.entries){const g=f.resolvedInput||f.input;if(f.resolvedInput=await(f.transform?f.transform(g):g),f.resolvedInput)for(const m of await Ev(f)){const n={tag:m,entry:f,resolvedOptions:u.resolvedOptions};await i.callHook("tag:normalise",n),o.tags.push(n.tag)}}return await i.callHook("tags:beforeResolve",o),await i.callHook("tags:resolve",o),await i.callHook("tags:afterResolve",o),o.tags},ssr:w};return[Rv,Nv,Iv,Fv,Uv,Vv,Hv,zv,...(r==null?void 0:r.plugins)||[]].forEach(o=>u.use(o)),u.hooks.callHook("init",u),u}function Xv(){return sh}const Yv=Sf[0]==="3";function $v(r){return typeof r=="function"?r():Vt(r)}function fi(r){if(r instanceof Promise||r instanceof Date||r instanceof RegExp)return r;const i=$v(r);if(!r||!i)return i;if(Array.isArray(i))return i.map(w=>fi(w));if(typeof i=="object"){const w={};for(const t in i)if(Object.prototype.hasOwnProperty.call(i,t)){if(t==="titleTemplate"||t[0]==="o"&&t[1]==="n"){w[t]=Vt(i[t]);continue}w[t]=fi(i[t])}return w}return i}const Zv={hooks:{"entries:resolve":r=>{for(const i of r.entries)i.resolvedInput=fi(i.input)}}},ih="usehead";function Kv(r){return{install(w){Yv&&(w.config.globalProperties.$unhead=r,w.config.globalProperties.$head=r,w.provide(ih,r))}}.install}function Qv(r={}){r.domDelayFn=r.domDelayFn||(w=>Hr(()=>setTimeout(()=>w(),0)));const i=Wv(r);return i.use(Zv),i.install=Kv(i),i}const qa=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},Xa="__unhead_injection_handler__";function Jv(r){qa[Xa]=r}function e0(){if(Xa in qa)return qa[Xa]();const r=zt(ih);return r||Xv()}function t0(r,i={}){const w=i.head||e0();if(w)return w.ssr?w.push(r,i):r0(w,r,i)}function r0(r,i,w={}){const t=mt(!1),x=mt({});fn(()=>{x.value=t.value?{}:fi(i)});const v=r.push(x.value,w);return Bn(x,u=>{v.patch(u)}),ao()&&(gs(()=>{v.dispose()}),Vd(()=>{t.value=!0}),Gd(()=>{t.value=!1})),v}function n0(r,i){const{title:w,titleTemplate:t,...x}=r;return t0({title:w,titleTemplate:t,_flatMeta:x},{...i,transform(v){const s=Ol({...v._flatMeta});return delete v._flatMeta,{...v,meta:s}}})}const o0={nuxt:{buildId:"8ac6cfc2-8695-46be-9b06-7ad33f3a3d43"}},s0=Qg(o0);function ah(){const r=Dt();return r._appConfig||(r._appConfig=qn(s0)),r._appConfig}const i0=!1,Ya=!1,a0=!1,l0={componentName:"NuxtLink"},uw={deep:!0},cw={},u0="#__nuxt";let $s,lh;function c0(){var i;const r=(i=ah().nuxt)==null?void 0:i.buildId;return $s=$fetch(Ml(`builds/meta/${r}.json`)),$s.then(w=>{lh=Kg(w.matcher)}),$s}function Ci(){return $s||c0()}async function Pl(r){return await Ci(),Hf({},...lh.matchAll(r).reverse())}function Ec(r,i={}){const w=f0(r,i),t=Dt(),x=t._payloadCache=t._payloadCache||{};return w in x||(x[w]=h0(r).then(v=>v?uh(w).then(s=>s||(delete x[w],null)):(x[w]=null,null))),x[w]}const d0="_payload.json";function f0(r,i={}){var x;const w=new URL(r,"http://localhost");if(w.host!=="localhost"||jn(w.pathname,{acceptRelative:!0}))throw new Error("Payload URL must not include hostname: "+r);const t=i.hash||(i.fresh?Date.now():(x=ah().nuxt)==null?void 0:x.buildId);return Si(Ei().app.baseURL,w.pathname,d0+(t?`?${t}`:""))}async function uh(r){const i=fetch(r).then(w=>w.text().then(ch));try{return await i}catch(w){console.warn("[nuxt] Cannot load payload ",r,w)}return null}async function h0(r=Ti().path){if(r=ji(r),(await Ci()).prerendered.includes(r))return!0;const w=await Pl(r);return!!w.prerender&&!w.redirect}let Gs=null;async function p0(){if(Gs)return Gs;const r=document.getElementById("__NUXT_DATA__");if(!r)return{};const i=await ch(r.textContent||""),w=r.dataset.src?await uh(r.dataset.src):void 0;return Gs={...i,...w,...window.__NUXT__},Gs}async function ch(r){return await pv(r,Dt()._payloadRevivers)}function m0(r,i){Dt()._payloadRevivers[r]=i}const Tc={NuxtError:r=>Mi(r),EmptyShallowRef:r=>os(r==="_"?void 0:r==="0n"?BigInt(0):si(r)),EmptyRef:r=>mt(r==="_"?void 0:r==="0n"?BigInt(0):si(r)),ShallowRef:r=>os(r),ShallowReactive:r=>ps(r),Ref:r=>mt(r),Reactive:r=>qn(r)},y0=Sn({name:"nuxt:revive-payload:client",order:-30,async setup(r){let i,w;for(const t in Tc)m0(t,Tc[t]);Object.assign(r.payload,([i,w]=us(()=>r.runWithContext(p0)),i=await i,w(),i)),window.__NUXT__=r.payload}}),g0=[],v0=Sn({name:"nuxt:head",enforce:"pre",setup(r){const i=Qv({plugins:g0});Jv(()=>Dt().vueApp._context.provides.usehead),r.vueApp.use(i);{let w=!0;const t=async()=>{w=!1,await oh(i)};i.hooks.hook("dom:beforeRender",x=>{x.shouldRender=!w}),r.hooks.hook("page:start",()=>{w=!0}),r.hooks.hook("page:finish",()=>{r.isHydrating||t()}),r.hooks.hook("app:error",t),r.hooks.hook("app:suspense:resolve",t)}}});/*! - * vue-router v4.4.4 - * (c) 2024 Eduardo San Martin Morote - * @license MIT - */const go=typeof document<"u";function dh(r){return typeof r=="object"||"displayName"in r||"props"in r||"__vccOpts"in r}function b0(r){return r.__esModule||r[Symbol.toStringTag]==="Module"||r.default&&dh(r.default)}const xt=Object.assign;function aa(r,i){const w={};for(const t in i){const x=i[t];w[t]=nn(x)?x.map(r):r(x)}return w}const Jo=()=>{},nn=Array.isArray,fh=/#/g,_0=/&/g,w0=/\//g,x0=/=/g,j0=/\?/g,hh=/\+/g,S0=/%5B/g,E0=/%5D/g,ph=/%5E/g,T0=/%60/g,mh=/%7B/g,k0=/%7C/g,yh=/%7D/g,M0=/%20/g;function Al(r){return encodeURI(""+r).replace(k0,"|").replace(S0,"[").replace(E0,"]")}function C0(r){return Al(r).replace(mh,"{").replace(yh,"}").replace(ph,"^")}function $a(r){return Al(r).replace(hh,"%2B").replace(M0,"+").replace(fh,"%23").replace(_0,"%26").replace(T0,"`").replace(mh,"{").replace(yh,"}").replace(ph,"^")}function O0(r){return $a(r).replace(x0,"%3D")}function P0(r){return Al(r).replace(fh,"%23").replace(j0,"%3F")}function A0(r){return r==null?"":P0(r).replace(w0,"%2F")}function cs(r){try{return decodeURIComponent(""+r)}catch{}return""+r}const R0=/\/$/,L0=r=>r.replace(R0,"");function la(r,i,w="/"){let t,x={},v="",s="";const u=i.indexOf("#");let o=i.indexOf("?");return u=0&&(o=-1),o>-1&&(t=i.slice(0,o),v=i.slice(o+1,u>-1?u:i.length),x=r(v)),u>-1&&(t=t||i.slice(0,u),s=i.slice(u,i.length)),t=N0(t??i,w),{fullPath:t+(v&&"?")+v+s,path:t,query:x,hash:cs(s)}}function I0(r,i){const w=i.query?r(i.query):"";return i.path+(w&&"?")+w+(i.hash||"")}function kc(r,i){return!i||!r.toLowerCase().startsWith(i.toLowerCase())?r:r.slice(i.length)||"/"}function D0(r,i,w){const t=i.matched.length-1,x=w.matched.length-1;return t>-1&&t===x&&Co(i.matched[t],w.matched[x])&&gh(i.params,w.params)&&r(i.query)===r(w.query)&&i.hash===w.hash}function Co(r,i){return(r.aliasOf||r)===(i.aliasOf||i)}function gh(r,i){if(Object.keys(r).length!==Object.keys(i).length)return!1;for(const w in r)if(!F0(r[w],i[w]))return!1;return!0}function F0(r,i){return nn(r)?Mc(r,i):nn(i)?Mc(i,r):r===i}function Mc(r,i){return nn(i)?r.length===i.length&&r.every((w,t)=>w===i[t]):r.length===1&&r[0]===i}function N0(r,i){if(r.startsWith("/"))return r;if(!r)return i;const w=i.split("/"),t=r.split("/"),x=t[t.length-1];(x===".."||x===".")&&t.push("");let v=w.length-1,s,u;for(s=0;s1&&v--;else break;return w.slice(0,v).join("/")+"/"+t.slice(s).join("/")}const Kr={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0};var ds;(function(r){r.pop="pop",r.push="push"})(ds||(ds={}));var es;(function(r){r.back="back",r.forward="forward",r.unknown=""})(es||(es={}));function U0(r){if(!r)if(go){const i=document.querySelector("base");r=i&&i.getAttribute("href")||"/",r=r.replace(/^\w+:\/\/[^\/]+/,"")}else r="/";return r[0]!=="/"&&r[0]!=="#"&&(r="/"+r),L0(r)}const B0=/^[^#]+#/;function G0(r,i){return r.replace(B0,"#")+i}function V0(r,i){const w=document.documentElement.getBoundingClientRect(),t=r.getBoundingClientRect();return{behavior:i.behavior,left:t.left-w.left-(i.left||0),top:t.top-w.top-(i.top||0)}}const Oi=()=>({left:window.scrollX,top:window.scrollY});function H0(r){let i;if("el"in r){const w=r.el,t=typeof w=="string"&&w.startsWith("#"),x=typeof w=="string"?t?document.getElementById(w.slice(1)):document.querySelector(w):w;if(!x)return;i=V0(x,r)}else i=r;"scrollBehavior"in document.documentElement.style?window.scrollTo(i):window.scrollTo(i.left!=null?i.left:window.scrollX,i.top!=null?i.top:window.scrollY)}function Cc(r,i){return(history.state?history.state.position-i:-1)+r}const Za=new Map;function z0(r,i){Za.set(r,i)}function W0(r){const i=Za.get(r);return Za.delete(r),i}let q0=()=>location.protocol+"//"+location.host;function vh(r,i){const{pathname:w,search:t,hash:x}=i,v=r.indexOf("#");if(v>-1){let u=x.includes(r.slice(v))?r.slice(v).length:1,o=x.slice(u);return o[0]!=="/"&&(o="/"+o),kc(o,"")}return kc(w,r)+t+x}function X0(r,i,w,t){let x=[],v=[],s=null;const u=({state:n})=>{const a=vh(r,location),l=w.value,d=i.value;let y=0;if(n){if(w.value=a,i.value=n,s&&s===l){s=null;return}y=d?n.position-d.position:0}else t(a);x.forEach(h=>{h(w.value,l,{delta:y,type:ds.pop,direction:y?y>0?es.forward:es.back:es.unknown})})};function o(){s=w.value}function f(n){x.push(n);const a=()=>{const l=x.indexOf(n);l>-1&&x.splice(l,1)};return v.push(a),a}function g(){const{history:n}=window;n.state&&n.replaceState(xt({},n.state,{scroll:Oi()}),"")}function m(){for(const n of v)n();v=[],window.removeEventListener("popstate",u),window.removeEventListener("beforeunload",g)}return window.addEventListener("popstate",u),window.addEventListener("beforeunload",g,{passive:!0}),{pauseListeners:o,listen:f,destroy:m}}function Oc(r,i,w,t=!1,x=!1){return{back:r,current:i,forward:w,replaced:t,position:window.history.length,scroll:x?Oi():null}}function Y0(r){const{history:i,location:w}=window,t={value:vh(r,w)},x={value:i.state};x.value||v(t.value,{back:null,current:t.value,forward:null,position:i.length-1,replaced:!0,scroll:null},!0);function v(o,f,g){const m=r.indexOf("#"),n=m>-1?(w.host&&document.querySelector("base")?r:r.slice(m))+o:q0()+r+o;try{i[g?"replaceState":"pushState"](f,"",n),x.value=f}catch(a){console.error(a),w[g?"replace":"assign"](n)}}function s(o,f){const g=xt({},i.state,Oc(x.value.back,o,x.value.forward,!0),f,{position:x.value.position});v(o,g,!0),t.value=o}function u(o,f){const g=xt({},x.value,i.state,{forward:o,scroll:Oi()});v(g.current,g,!0);const m=xt({},Oc(t.value,o,null),{position:g.position+1},f);v(o,m,!1),t.value=o}return{location:t,state:x,push:u,replace:s}}function bh(r){r=U0(r);const i=Y0(r),w=X0(r,i.state,i.location,i.replace);function t(v,s=!0){s||w.pauseListeners(),history.go(v)}const x=xt({location:"",base:r,go:t,createHref:G0.bind(null,r)},i,w);return Object.defineProperty(x,"location",{enumerable:!0,get:()=>i.location.value}),Object.defineProperty(x,"state",{enumerable:!0,get:()=>i.state.value}),x}function $0(r){return r=location.host?r||location.pathname+location.search:"",r.includes("#")||(r+="#"),bh(r)}function Z0(r){return typeof r=="string"||r&&typeof r=="object"}function _h(r){return typeof r=="string"||typeof r=="symbol"}const wh=Symbol("");var Pc;(function(r){r[r.aborted=4]="aborted",r[r.cancelled=8]="cancelled",r[r.duplicated=16]="duplicated"})(Pc||(Pc={}));function Oo(r,i){return xt(new Error,{type:r,[wh]:!0},i)}function gn(r,i){return r instanceof Error&&wh in r&&(i==null||!!(r.type&i))}const Ac="[^/]+?",K0={sensitive:!1,strict:!1,start:!0,end:!0},Q0=/[.+*?^${}()[\]/\\]/g;function J0(r,i){const w=xt({},K0,i),t=[];let x=w.start?"^":"";const v=[];for(const f of r){const g=f.length?[]:[90];w.strict&&!f.length&&(x+="/");for(let m=0;mi.length?i.length===1&&i[0]===80?1:-1:0}function xh(r,i){let w=0;const t=r.score,x=i.score;for(;w0&&i[i.length-1]<0}const tb={type:0,value:""},rb=/[a-zA-Z0-9_]/;function nb(r){if(!r)return[[]];if(r==="/")return[[tb]];if(!r.startsWith("/"))throw new Error(`Invalid path "${r}"`);function i(a){throw new Error(`ERR (${w})/"${f}": ${a}`)}let w=0,t=w;const x=[];let v;function s(){v&&x.push(v),v=[]}let u=0,o,f="",g="";function m(){f&&(w===0?v.push({type:0,value:f}):w===1||w===2||w===3?(v.length>1&&(o==="*"||o==="+")&&i(`A repeatable param (${f}) must be alone in its segment. eg: '/:ids+.`),v.push({type:1,value:f,regexp:g,repeatable:o==="*"||o==="+",optional:o==="*"||o==="?"})):i("Invalid state to consume buffer"),f="")}function n(){f+=o}for(;u{s(p)}:Jo}function s(m){if(_h(m)){const n=t.get(m);n&&(t.delete(m),w.splice(w.indexOf(n),1),n.children.forEach(s),n.alias.forEach(s))}else{const n=w.indexOf(m);n>-1&&(w.splice(n,1),m.record.name&&t.delete(m.record.name),m.children.forEach(s),m.alias.forEach(s))}}function u(){return w}function o(m){const n=ub(m,w);w.splice(n,0,m),m.record.name&&!Ic(m)&&t.set(m.record.name,m)}function f(m,n){let a,l={},d,y;if("name"in m&&m.name){if(a=t.get(m.name),!a)throw Oo(1,{location:m});y=a.record.name,l=xt(Lc(n.params,a.keys.filter(p=>!p.optional).concat(a.parent?a.parent.keys.filter(p=>p.optional):[]).map(p=>p.name)),m.params&&Lc(m.params,a.keys.map(p=>p.name))),d=a.stringify(l)}else if(m.path!=null)d=m.path,a=w.find(p=>p.re.test(d)),a&&(l=a.parse(d),y=a.record.name);else{if(a=n.name?t.get(n.name):w.find(p=>p.re.test(n.path)),!a)throw Oo(1,{location:m,currentLocation:n});y=a.record.name,l=xt({},n.params,m.params),d=a.stringify(l)}const h=[];let c=a;for(;c;)h.unshift(c.record),c=c.parent;return{name:y,path:d,params:l,matched:h,meta:lb(h)}}r.forEach(m=>v(m));function g(){w.length=0,t.clear()}return{addRoute:v,resolve:f,removeRoute:s,clearRoutes:g,getRoutes:u,getRecordMatcher:x}}function Lc(r,i){const w={};for(const t of i)t in r&&(w[t]=r[t]);return w}function ib(r){return{path:r.path,redirect:r.redirect,name:r.name,meta:r.meta||{},aliasOf:void 0,beforeEnter:r.beforeEnter,props:ab(r),children:r.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},mods:{},components:"components"in r?r.components||null:r.component&&{default:r.component}}}function ab(r){const i={},w=r.props||!1;if("component"in r)i.default=w;else for(const t in r.components)i[t]=typeof w=="object"?w[t]:w;return i}function Ic(r){for(;r;){if(r.record.aliasOf)return!0;r=r.parent}return!1}function lb(r){return r.reduce((i,w)=>xt(i,w.meta),{})}function Dc(r,i){const w={};for(const t in r)w[t]=t in i?i[t]:r[t];return w}function ub(r,i){let w=0,t=i.length;for(;w!==t;){const v=w+t>>1;xh(r,i[v])<0?t=v:w=v+1}const x=cb(r);return x&&(t=i.lastIndexOf(x,t-1)),t}function cb(r){let i=r;for(;i=i.parent;)if(jh(i)&&xh(r,i)===0)return i}function jh({record:r}){return!!(r.name||r.components&&Object.keys(r.components).length||r.redirect)}function db(r){const i={};if(r===""||r==="?")return i;const t=(r[0]==="?"?r.slice(1):r).split("&");for(let x=0;xv&&$a(v)):[t&&$a(t)]).forEach(v=>{v!==void 0&&(i+=(i.length?"&":"")+w,v!=null&&(i+="="+v))})}return i}function fb(r){const i={};for(const w in r){const t=r[w];t!==void 0&&(i[w]=nn(t)?t.map(x=>x==null?null:""+x):t==null?t:""+t)}return i}const hb=Symbol(""),Nc=Symbol(""),Rl=Symbol(""),Ll=Symbol(""),Ka=Symbol("");function zo(){let r=[];function i(t){return r.push(t),()=>{const x=r.indexOf(t);x>-1&&r.splice(x,1)}}function w(){r=[]}return{add:i,list:()=>r.slice(),reset:w}}function In(r,i,w,t,x,v=s=>s()){const s=t&&(t.enterCallbacks[x]=t.enterCallbacks[x]||[]);return()=>new Promise((u,o)=>{const f=n=>{n===!1?o(Oo(4,{from:w,to:i})):n instanceof Error?o(n):Z0(n)?o(Oo(2,{from:i,to:n})):(s&&t.enterCallbacks[x]===s&&typeof n=="function"&&s.push(n),u())},g=v(()=>r.call(t&&t.instances[x],i,w,f));let m=Promise.resolve(g);r.length<3&&(m=m.then(f)),m.catch(n=>o(n))})}function ua(r,i,w,t,x=v=>v()){const v=[];for(const s of r)for(const u in s.components){let o=s.components[u];if(!(i!=="beforeRouteEnter"&&!s.instances[u]))if(dh(o)){const g=(o.__vccOpts||o)[i];g&&v.push(In(g,w,t,s,u,x))}else{let f=o();v.push(()=>f.then(g=>{if(!g)throw new Error(`Couldn't resolve component "${u}" at "${s.path}"`);const m=b0(g)?g.default:g;s.mods[u]=g,s.components[u]=m;const a=(m.__vccOpts||m)[i];return a&&In(a,w,t,s,u,x)()}))}}return v}function Uc(r){const i=zt(Rl),w=zt(Ll),t=jt(()=>{const o=Vt(r.to);return i.resolve(o)}),x=jt(()=>{const{matched:o}=t.value,{length:f}=o,g=o[f-1],m=w.matched;if(!g||!m.length)return-1;const n=m.findIndex(Co.bind(null,g));if(n>-1)return n;const a=Bc(o[f-2]);return f>1&&Bc(g)===a&&m[m.length-1].path!==a?m.findIndex(Co.bind(null,o[f-2])):n}),v=jt(()=>x.value>-1&&gb(w.params,t.value.params)),s=jt(()=>x.value>-1&&x.value===w.matched.length-1&&gh(w.params,t.value.params));function u(o={}){return yb(o)?i[Vt(r.replace)?"replace":"push"](Vt(r.to)).catch(Jo):Promise.resolve()}return{route:t,href:jt(()=>t.value.href),isActive:v,isExactActive:s,navigate:u}}const pb=gr({name:"RouterLink",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"}},useLink:Uc,setup(r,{slots:i}){const w=qn(Uc(r)),{options:t}=zt(Rl),x=jt(()=>({[Gc(r.activeClass,t.linkActiveClass,"router-link-active")]:w.isActive,[Gc(r.exactActiveClass,t.linkExactActiveClass,"router-link-exact-active")]:w.isExactActive}));return()=>{const v=i.default&&i.default(w);return r.custom?v:or("a",{"aria-current":w.isExactActive?r.ariaCurrentValue:null,href:w.href,onClick:w.navigate,class:x.value},v)}}}),mb=pb;function yb(r){if(!(r.metaKey||r.altKey||r.ctrlKey||r.shiftKey)&&!r.defaultPrevented&&!(r.button!==void 0&&r.button!==0)){if(r.currentTarget&&r.currentTarget.getAttribute){const i=r.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(i))return}return r.preventDefault&&r.preventDefault(),!0}}function gb(r,i){for(const w in i){const t=i[w],x=r[w];if(typeof t=="string"){if(t!==x)return!1}else if(!nn(x)||x.length!==t.length||t.some((v,s)=>v!==x[s]))return!1}return!0}function Bc(r){return r?r.aliasOf?r.aliasOf.path:r.path:""}const Gc=(r,i,w)=>r??i??w,vb=gr({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(r,{attrs:i,slots:w}){const t=zt(Ka),x=jt(()=>r.route||t.value),v=zt(Nc,0),s=jt(()=>{let f=Vt(v);const{matched:g}=x.value;let m;for(;(m=g[f])&&!m.components;)f++;return f}),u=jt(()=>x.value.matched[s.value]);qr(Nc,jt(()=>s.value+1)),qr(hb,u),qr(Ka,x);const o=mt();return Bn(()=>[o.value,u.value,r.name],([f,g,m],[n,a,l])=>{g&&(g.instances[m]=f,a&&a!==g&&f&&f===n&&(g.leaveGuards.size||(g.leaveGuards=a.leaveGuards),g.updateGuards.size||(g.updateGuards=a.updateGuards))),f&&g&&(!a||!Co(g,a)||!n)&&(g.enterCallbacks[m]||[]).forEach(d=>d(f))},{flush:"post"}),()=>{const f=x.value,g=r.name,m=u.value,n=m&&m.components[g];if(!n)return Vc(w.default,{Component:n,route:f});const a=m.props[g],l=a?a===!0?f.params:typeof a=="function"?a(f):a:null,y=or(n,xt({},l,i,{onVnodeUnmounted:h=>{h.component.isUnmounted&&(m.instances[g]=null)},ref:o}));return Vc(w.default,{Component:y,route:f})||y}}});function Vc(r,i){if(!r)return null;const w=r(i);return w.length===1?w[0]:w}const Sh=vb;function bb(r){const i=sb(r.routes,r),w=r.parseQuery||db,t=r.stringifyQuery||Fc,x=r.history,v=zo(),s=zo(),u=zo(),o=os(Kr);let f=Kr;go&&r.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const g=aa.bind(null,Z=>""+Z),m=aa.bind(null,A0),n=aa.bind(null,cs);function a(Z,ee){let ne,ue;return _h(Z)?(ne=i.getRecordMatcher(Z),ue=ee):ue=Z,i.addRoute(ue,ne)}function l(Z){const ee=i.getRecordMatcher(Z);ee&&i.removeRoute(ee)}function d(){return i.getRoutes().map(Z=>Z.record)}function y(Z){return!!i.getRecordMatcher(Z)}function h(Z,ee){if(ee=xt({},ee||o.value),typeof Z=="string"){const z=la(w,Z,ee.path),te=i.resolve({path:z.path},ee),ce=x.createHref(z.fullPath);return xt(z,te,{params:n(te.params),hash:cs(z.hash),redirectedFrom:void 0,href:ce})}let ne;if(Z.path!=null)ne=xt({},Z,{path:la(w,Z.path,ee.path).path});else{const z=xt({},Z.params);for(const te in z)z[te]==null&&delete z[te];ne=xt({},Z,{params:m(z)}),ee.params=m(ee.params)}const ue=i.resolve(ne,ee),ie=Z.hash||"";ue.params=g(n(ue.params));const he=I0(t,xt({},Z,{hash:C0(ie),path:ue.path})),$=x.createHref(he);return xt({fullPath:he,hash:ie,query:t===Fc?fb(Z.query):Z.query||{}},ue,{redirectedFrom:void 0,href:$})}function c(Z){return typeof Z=="string"?la(w,Z,o.value.path):xt({},Z)}function p(Z,ee){if(f!==Z)return Oo(8,{from:ee,to:Z})}function b(Z){return E(Z)}function j(Z){return b(xt(c(Z),{replace:!0}))}function M(Z){const ee=Z.matched[Z.matched.length-1];if(ee&&ee.redirect){const{redirect:ne}=ee;let ue=typeof ne=="function"?ne(Z):ne;return typeof ue=="string"&&(ue=ue.includes("?")||ue.includes("#")?ue=c(ue):{path:ue},ue.params={}),xt({query:Z.query,hash:Z.hash,params:ue.path!=null?{}:Z.params},ue)}}function E(Z,ee){const ne=f=h(Z),ue=o.value,ie=Z.state,he=Z.force,$=Z.replace===!0,z=M(ne);if(z)return E(xt(c(z),{state:typeof z=="object"?xt({},ie,z.state):ie,force:he,replace:$}),ee||ne);const te=ne;te.redirectedFrom=ee;let ce;return!he&&D0(t,ue,ne)&&(ce=Oo(16,{to:te,from:ue}),J(ue,ue,!0,!1)),(ce?Promise.resolve(ce):L(te,ue)).catch(me=>gn(me)?gn(me,2)?me:K(me):H(me,te,ue)).then(me=>{if(me){if(gn(me,2))return E(xt({replace:$},c(me.to),{state:typeof me.to=="object"?xt({},ie,me.to.state):ie,force:he}),ee||te)}else me=I(te,ue,!0,$,ie);return C(te,ue,me),me})}function k(Z,ee){const ne=p(Z,ee);return ne?Promise.reject(ne):Promise.resolve()}function O(Z){const ee=D.values().next().value;return ee&&typeof ee.runWithContext=="function"?ee.runWithContext(Z):Z()}function L(Z,ee){let ne;const[ue,ie,he]=_b(Z,ee);ne=ua(ue.reverse(),"beforeRouteLeave",Z,ee);for(const z of ue)z.leaveGuards.forEach(te=>{ne.push(In(te,Z,ee))});const $=k.bind(null,Z,ee);return ne.push($),q(ne).then(()=>{ne=[];for(const z of v.list())ne.push(In(z,Z,ee));return ne.push($),q(ne)}).then(()=>{ne=ua(ie,"beforeRouteUpdate",Z,ee);for(const z of ie)z.updateGuards.forEach(te=>{ne.push(In(te,Z,ee))});return ne.push($),q(ne)}).then(()=>{ne=[];for(const z of he)if(z.beforeEnter)if(nn(z.beforeEnter))for(const te of z.beforeEnter)ne.push(In(te,Z,ee));else ne.push(In(z.beforeEnter,Z,ee));return ne.push($),q(ne)}).then(()=>(Z.matched.forEach(z=>z.enterCallbacks={}),ne=ua(he,"beforeRouteEnter",Z,ee,O),ne.push($),q(ne))).then(()=>{ne=[];for(const z of s.list())ne.push(In(z,Z,ee));return ne.push($),q(ne)}).catch(z=>gn(z,8)?z:Promise.reject(z))}function C(Z,ee,ne){u.list().forEach(ue=>O(()=>ue(Z,ee,ne)))}function I(Z,ee,ne,ue,ie){const he=p(Z,ee);if(he)return he;const $=ee===Kr,z=go?history.state:{};ne&&(ue||$?x.replace(Z.fullPath,xt({scroll:$&&z&&z.scroll},ie)):x.push(Z.fullPath,ie)),o.value=Z,J(Z,ee,ne,$),K()}let A;function N(){A||(A=x.listen((Z,ee,ne)=>{if(!G.listening)return;const ue=h(Z),ie=M(ue);if(ie){E(xt(ie,{replace:!0}),ue).catch(Jo);return}f=ue;const he=o.value;go&&z0(Cc(he.fullPath,ne.delta),Oi()),L(ue,he).catch($=>gn($,12)?$:gn($,2)?(E($.to,ue).then(z=>{gn(z,20)&&!ne.delta&&ne.type===ds.pop&&x.go(-1,!1)}).catch(Jo),Promise.reject()):(ne.delta&&x.go(-ne.delta,!1),H($,ue,he))).then($=>{$=$||I(ue,he,!1),$&&(ne.delta&&!gn($,8)?x.go(-ne.delta,!1):ne.type===ds.pop&&gn($,20)&&x.go(-1,!1)),C(ue,he,$)}).catch(Jo)}))}let F=zo(),B=zo(),W;function H(Z,ee,ne){K(Z);const ue=B.list();return ue.length?ue.forEach(ie=>ie(Z,ee,ne)):console.error(Z),Promise.reject(Z)}function V(){return W&&o.value!==Kr?Promise.resolve():new Promise((Z,ee)=>{F.add([Z,ee])})}function K(Z){return W||(W=!Z,N(),F.list().forEach(([ee,ne])=>Z?ne(Z):ee()),F.reset()),Z}function J(Z,ee,ne,ue){const{scrollBehavior:ie}=r;if(!go||!ie)return Promise.resolve();const he=!ne&&W0(Cc(Z.fullPath,0))||(ue||!ne)&&history.state&&history.state.scroll||null;return Hr().then(()=>ie(Z,ee,he)).then($=>$&&H0($)).catch($=>H($,Z,ee))}const le=Z=>x.go(Z);let T;const D=new Set,G={currentRoute:o,listening:!0,addRoute:a,removeRoute:l,clearRoutes:i.clearRoutes,hasRoute:y,getRoutes:d,resolve:h,options:r,push:b,replace:j,go:le,back:()=>le(-1),forward:()=>le(1),beforeEach:v.add,beforeResolve:s.add,afterEach:u.add,onError:B.add,isReady:V,install(Z){const ee=this;Z.component("RouterLink",mb),Z.component("RouterView",Sh),Z.config.globalProperties.$router=ee,Object.defineProperty(Z.config.globalProperties,"$route",{enumerable:!0,get:()=>Vt(o)}),go&&!T&&o.value===Kr&&(T=!0,b(x.location).catch(ie=>{}));const ne={};for(const ie in Kr)Object.defineProperty(ne,ie,{get:()=>o.value[ie],enumerable:!0});Z.provide(Rl,ee),Z.provide(Ll,ps(ne)),Z.provide(Ka,o);const ue=Z.unmount;D.add(Z),Z.unmount=function(){D.delete(Z),D.size<1&&(f=Kr,A&&A(),A=null,o.value=Kr,T=!1,W=!1),ue()}}};function q(Z){return Z.reduce((ee,ne)=>ee.then(()=>O(ne)),Promise.resolve())}return G}function _b(r,i){const w=[],t=[],x=[],v=Math.max(i.matched.length,r.matched.length);for(let s=0;sCo(f,u))?t.push(u):w.push(u));const o=r.matched[s];o&&(i.matched.find(f=>Co(f,o))||x.push(o))}return[w,t,x]}function wb(r){return zt(Ll)}const xb=(r,i)=>i.path.replace(/(:\w+)\([^)]+\)/g,"$1").replace(/(:\w+)[?+*]/g,"$1").replace(/:\w+/g,w=>{var t;return((t=r.params[w.slice(1)])==null?void 0:t.toString())||""}),Qa=(r,i)=>{const w=r.route.matched.find(x=>{var v;return((v=x.components)==null?void 0:v.default)===r.Component.type}),t=i??(w==null?void 0:w.meta.key)??(w&&xb(r.route,w));return typeof t=="function"?t(r.route):t},jb=(r,i)=>({default:()=>r?or(fm,r===!0?{}:r,i):i});function Il(r){return Array.isArray(r)?r:[r]}const Sb="modulepreload",Eb=function(r,i){return new URL(r,i).href},Hc={},Tb=function(i,w,t){let x=Promise.resolve();if(w&&w.length>0){const v=document.getElementsByTagName("link"),s=document.querySelector("meta[property=csp-nonce]"),u=(s==null?void 0:s.nonce)||(s==null?void 0:s.getAttribute("nonce"));x=Promise.allSettled(w.map(o=>{if(o=Eb(o,t),o in Hc)return;Hc[o]=!0;const f=o.endsWith(".css"),g=f?'[rel="stylesheet"]':"";if(!!t)for(let a=v.length-1;a>=0;a--){const l=v[a];if(l.href===o&&(!f||l.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${o}"]${g}`))return;const n=document.createElement("link");if(n.rel=f?"stylesheet":Sb,f||(n.as="script"),n.crossOrigin="",n.href=o,u&&n.setAttribute("nonce",u),document.head.appendChild(n),f)return new Promise((a,l)=>{n.addEventListener("load",a),n.addEventListener("error",()=>l(new Error(`Unable to preload CSS for ${o}`)))})}))}return x.then(v=>{for(const s of v||[]){if(s.status!=="rejected")continue;const u=new Event("vite:preloadError",{cancelable:!0});if(u.payload=s.reason,window.dispatchEvent(u),!u.defaultPrevented)throw s.reason}return i()})},rt=(...r)=>Tb(...r).catch(i=>{const w=new Event("nuxt.preloadError");throw w.payload=i,window.dispatchEvent(w),i}),ca=null,da=null,Tr={layout:"empty"},fa=null,ha=null,pa=null,kr={layout:"light"},Mr={layout:"light"},Cr={layout:"light"},ma=null,Or={layout:"light"},Pr={layout:"light"},Ar={layout:"light"},Rr={layout:"light"},Lr={layout:"light"},Ir={layout:"light"},Dr={layout:"light"},Fr={layout:"light"},ya=null,zc=[{name:"articles-slug",path:"/articles/:slug(.*)*",meta:{},alias:[],redirect:ca==null?void 0:ca.redirect,component:()=>rt(()=>import("./DV8CRu_y.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9]),import.meta.url).then(r=>r.default||r)},{name:"articles",path:"/articles",meta:{},alias:[],redirect:da==null?void 0:da.redirect,component:()=>rt(()=>import("./CMGdJvMz.js"),__vite__mapDeps([10,1,2,3,4,5,6,7,8]),import.meta.url).then(r=>r.default||r)},{name:(Tr==null?void 0:Tr.name)??"card",path:(Tr==null?void 0:Tr.path)??"/card",meta:Tr||{},alias:(Tr==null?void 0:Tr.alias)||[],redirect:Tr==null?void 0:Tr.redirect,component:()=>rt(()=>import("./DrUr0h-s.js"),[],import.meta.url).then(r=>r.default||r)},{name:"examples-nested_transitions",path:"/examples/nested_transitions",meta:{},alias:[],redirect:fa==null?void 0:fa.redirect,component:()=>rt(()=>import("./Ml_4v_Rc.js"),[],import.meta.url).then(r=>r.default||r)},{name:"index",path:"/",meta:{},alias:[],redirect:ha==null?void 0:ha.redirect,component:()=>rt(()=>import("./D2yfouAe.js"),__vite__mapDeps([11,12,8,5,4]),import.meta.url).then(r=>r.default||r)},{name:"playground-audio",path:"/playground/audio",meta:{},alias:[],redirect:pa==null?void 0:pa.redirect,component:()=>rt(()=>import("./Ddr6mL0e.js"),[],import.meta.url).then(r=>r.default||r)},{name:(kr==null?void 0:kr.name)??"playground-chords",path:(kr==null?void 0:kr.path)??"/playground/chords",meta:kr||{},alias:(kr==null?void 0:kr.alias)||[],redirect:kr==null?void 0:kr.redirect,component:()=>rt(()=>import("./DYh1WRot.js"),[],import.meta.url).then(r=>r.default||r)},{name:(Mr==null?void 0:Mr.name)??"playground-conway",path:(Mr==null?void 0:Mr.path)??"/playground/conway",meta:Mr||{},alias:(Mr==null?void 0:Mr.alias)||[],redirect:Mr==null?void 0:Mr.redirect,component:()=>rt(()=>import("./B09kizko.js"),[],import.meta.url).then(r=>r.default||r)},{name:(Cr==null?void 0:Cr.name)??"playground-french",path:(Cr==null?void 0:Cr.path)??"/playground/french",meta:Cr||{},alias:(Cr==null?void 0:Cr.alias)||[],redirect:Cr==null?void 0:Cr.redirect,component:()=>rt(()=>import("./DS2wgvBY.js"),__vite__mapDeps([13,5,7]),import.meta.url).then(r=>r.default||r)},{name:"playground",path:"/playground",meta:{},alias:[],redirect:ma==null?void 0:ma.redirect,component:()=>rt(()=>import("./DKixc0ER.js"),__vite__mapDeps([14,12]),import.meta.url).then(r=>r.default||r)},{name:(Or==null?void 0:Or.name)??"playground-matrix",path:(Or==null?void 0:Or.path)??"/playground/matrix",meta:Or||{},alias:(Or==null?void 0:Or.alias)||[],redirect:Or==null?void 0:Or.redirect,component:()=>rt(()=>import("./BbJBDj-J.js"),[],import.meta.url).then(r=>r.default||r)},{name:(Pr==null?void 0:Pr.name)??"playground-metronome",path:(Pr==null?void 0:Pr.path)??"/playground/metronome",meta:Pr||{},alias:(Pr==null?void 0:Pr.alias)||[],redirect:Pr==null?void 0:Pr.redirect,component:()=>rt(()=>import("./BMjn8cbr.js"),[],import.meta.url).then(r=>r.default||r)},{name:(Ar==null?void 0:Ar.name)??"playground-midi",path:(Ar==null?void 0:Ar.path)??"/playground/midi",meta:Ar||{},alias:(Ar==null?void 0:Ar.alias)||[],redirect:Ar==null?void 0:Ar.redirect,component:()=>rt(()=>import("./B7NK_Nbm.js"),[],import.meta.url).then(r=>r.default||r)},{name:(Rr==null?void 0:Rr.name)??"playground-palettes-mountains",path:(Rr==null?void 0:Rr.path)??"/playground/palettes/mountains",meta:Rr||{},alias:(Rr==null?void 0:Rr.alias)||[],redirect:Rr==null?void 0:Rr.redirect,component:()=>rt(()=>import("./_5NWYBcI.js"),[],import.meta.url).then(r=>r.default||r)},{name:(Lr==null?void 0:Lr.name)??"playground-palettes-variance",path:(Lr==null?void 0:Lr.path)??"/playground/palettes/variance",meta:Lr||{},alias:(Lr==null?void 0:Lr.alias)||[],redirect:Lr==null?void 0:Lr.redirect,component:()=>rt(()=>import("./Ie0IFvhY.js"),[],import.meta.url).then(r=>r.default||r)},{name:(Ir==null?void 0:Ir.name)??"playground-plotter",path:(Ir==null?void 0:Ir.path)??"/playground/plotter",meta:Ir||{},alias:(Ir==null?void 0:Ir.alias)||[],redirect:Ir==null?void 0:Ir.redirect,component:()=>rt(()=>import("./BExJZFgy.js"),[],import.meta.url).then(r=>r.default||r)},{name:(Dr==null?void 0:Dr.name)??"playground-tiling",path:(Dr==null?void 0:Dr.path)??"/playground/tiling",meta:Dr||{},alias:(Dr==null?void 0:Dr.alias)||[],redirect:Dr==null?void 0:Dr.redirect,component:()=>rt(()=>import("./BdajRVA-.js"),[],import.meta.url).then(r=>r.default||r)},{name:(Fr==null?void 0:Fr.name)??"playground-waves",path:(Fr==null?void 0:Fr.path)??"/playground/waves",meta:Fr||{},alias:(Fr==null?void 0:Fr.alias)||[],redirect:Fr==null?void 0:Fr.redirect,component:()=>rt(()=>import("./BbWmv1K-.js"),[],import.meta.url).then(r=>r.default||r)},{name:"talks",path:"/talks",meta:{},alias:[],redirect:ya==null?void 0:ya.redirect,component:()=>rt(()=>import("./DMa1cH9I.js"),[],import.meta.url).then(r=>r.default||r)}],Eh=(r,i,w)=>(i=i===!0?{}:i,{default:()=>{var t;return i?or(r,i,w):(t=w.default)==null?void 0:t.call(w)}});function Wc(r){const i=(r==null?void 0:r.meta.key)??r.path.replace(/(:\w+)\([^)]+\)/g,"$1").replace(/(:\w+)[?+*]/g,"$1").replace(/:\w+/g,w=>{var t;return((t=r.params[w.slice(1)])==null?void 0:t.toString())||""});return typeof i=="function"?i(r):i}function kb(r,i){return r===i||i===Kr?!1:Wc(r)!==Wc(i)?!0:!r.matched.every((t,x)=>{var v,s;return t.components&&t.components.default===((s=(v=i.matched[x])==null?void 0:v.components)==null?void 0:s.default)})}const Mb={scrollBehavior(r,i,w){var f;const t=Dt(),x=((f=Xr().options)==null?void 0:f.scrollBehaviorType)??"auto";let v=w||void 0;const s=typeof r.meta.scrollToTop=="function"?r.meta.scrollToTop(r,i):r.meta.scrollToTop;if(!v&&i&&r&&s!==!1&&kb(r,i)&&(v={left:0,top:0}),r.path===i.path)return i.hash&&!r.hash?{left:0,top:0}:r.hash?{el:r.hash,top:qc(r.hash),behavior:x}:!1;const u=g=>!!(g.meta.pageTransition??Ya),o=u(i)&&u(r)?"page:transition:finish":"page:finish";return new Promise(g=>{t.hooks.hookOnce(o,async()=>{await new Promise(m=>setTimeout(m,0)),r.hash&&(v={el:r.hash,top:qc(r.hash),behavior:x}),g(v)})})}};function qc(r){try{const i=document.querySelector(r);if(i)return parseFloat(getComputedStyle(i).scrollMarginTop)}catch{}return 0}const Cb={hashMode:!1,scrollBehaviorType:"auto"},Nr={...Cb,...Mb},Ob=async r=>{var o;let i,w;if(!((o=r.meta)!=null&&o.validate))return;const t=Dt(),x=Xr();if(([i,w]=us(()=>Promise.resolve(r.meta.validate(r))),i=await i,w(),i)===!0)return;const s=Mi({statusCode:404,statusMessage:`Page Not Found: ${r.fullPath}`,data:{path:r.fullPath}}),u=x.beforeResolve(f=>{if(u(),f===r){const g=x.afterEach(async()=>{g(),await t.runWithContext(()=>bo(s)),window.history.pushState({},"",r.fullPath)});return!1}})},Pb=async r=>{let i,w;const t=([i,w]=us(()=>Pl(r.path)),i=await i,w(),i);if(t.redirect)return jn(t.redirect,{acceptRelative:!0})?(window.location.href=t.redirect,!1):t.redirect},Ab=[Ob,Pb],ts={};function Rb(r,i,w){const{pathname:t,search:x,hash:v}=i,s=r.indexOf("#");if(s>-1){const f=v.includes(r.slice(s))?r.slice(s).length:1;let g=v.slice(f);return g[0]!=="/"&&(g="/"+g),hc(g,"")}const u=hc(t,r),o=!w||mg(u,w,{trailingSlash:!0})?u:w;return o+(o.includes("?")?"":x)+v}const Lb=Sn({name:"nuxt:router",enforce:"pre",async setup(r){var y,h;let i,w,t=Ei().app.baseURL;Nr.hashMode&&!t.includes("#")&&(t+="#");const x=((y=Nr.history)==null?void 0:y.call(Nr,t))??(Nr.hashMode?$0(t):bh(t)),v=((h=Nr.routes)==null?void 0:h.call(Nr,zc))??zc;let s;const u=bb({...Nr,scrollBehavior:(c,p,b)=>{if(p===Kr){s=b;return}if(Nr.scrollBehavior){if(u.options.scrollBehavior=Nr.scrollBehavior,"scrollRestoration"in window.history){const j=u.beforeEach(()=>{j(),window.history.scrollRestoration="manual"})}return Nr.scrollBehavior(c,Kr,s||b)}},history:x,routes:v});"scrollRestoration"in window.history&&(window.history.scrollRestoration="auto"),r.vueApp.use(u);const o=os(u.currentRoute.value);u.afterEach((c,p)=>{o.value=p}),Object.defineProperty(r.vueApp.config.globalProperties,"previousRoute",{get:()=>o.value});const f=Rb(t,window.location,r.payload.path),g=os(u.currentRoute.value),m=()=>{g.value=u.currentRoute.value};r.hook("page:finish",m),u.afterEach((c,p)=>{var b,j,M,E;((j=(b=c.matched[0])==null?void 0:b.components)==null?void 0:j.default)===((E=(M=p.matched[0])==null?void 0:M.components)==null?void 0:E.default)&&m()});const n={};for(const c in g.value)Object.defineProperty(n,c,{get:()=>g.value[c]});r._route=ps(n),r._middleware=r._middleware||{global:[],named:{}};try{[i,w]=us(()=>u.isReady()),await i,w()}catch(c){[i,w]=us(()=>r.runWithContext(()=>bo(c))),await i,w()}const a=f!==u.currentRoute.value.fullPath?u.resolve(f):u.currentRoute.value;m();const l=r.payload.state._layout;u.beforeEach(async(c,p)=>{var b;await r.callHook("page:loading:start"),c.meta=qn(c.meta),r.isHydrating&&l&&!Vn(c.meta.layout)&&(c.meta.layout=l),r._processingMiddleware=!0;{const j=new Set([...Ab,...r._middleware.global]);for(const M of c.matched){const E=M.meta.middleware;if(E)for(const k of Il(E))j.add(k)}{const M=await r.runWithContext(()=>Pl(c.path));if(M.appMiddleware)for(const E in M.appMiddleware)M.appMiddleware[E]?j.add(E):j.delete(E)}for(const M of j){const E=typeof M=="string"?r._middleware.named[M]||await((b=ts[M])==null?void 0:b.call(ts).then(O=>O.default||O)):M;if(!E)throw new Error(`Unknown route middleware: '${M}'.`);const k=await r.runWithContext(()=>E(c,p));if(!r.payload.serverRendered&&r.isHydrating&&(k===!1||k instanceof Error)){const O=k||Ga({statusCode:404,statusMessage:`Page Not Found: ${f}`});return await r.runWithContext(()=>bo(O)),!1}if(k!==!0&&(k||k===!1))return k}}}),u.onError(async()=>{delete r._processingMiddleware,await r.callHook("page:loading:end")});const d=ki();return u.afterEach(async(c,p,b)=>{delete r._processingMiddleware,!r.isHydrating&&d.value&&await r.runWithContext(iv),b&&await r.callHook("page:loading:end"),c.matched.length===0&&await r.runWithContext(()=>bo(Ga({statusCode:404,fatal:!1,statusMessage:`Page not found: ${c.fullPath}`,data:{path:c.fullPath}})))}),r.hooks.hookOnce("app:created",async()=>{try{"name"in a&&(a.name=void 0),await u.replace({...a,force:!0}),u.options.scrollBehavior=Nr.scrollBehavior}catch(c){await r.runWithContext(()=>bo(c))}}),{provide:{router:u}}}}),Ja=globalThis.requestIdleCallback||(r=>{const i=Date.now(),w={didTimeout:!1,timeRemaining:()=>Math.max(0,50-(Date.now()-i))};return setTimeout(()=>{r(w)},1)}),Ib=globalThis.cancelIdleCallback||(r=>{clearTimeout(r)}),Dl=r=>{const i=Dt();i.isHydrating?i.hooks.hookOnce("app:suspense:resolve",()=>{Ja(r)}):Ja(r)},Db=Sn({name:"nuxt:payload",setup(r){Xr().beforeResolve(async(i,w)=>{if(i.path===w.path)return;const t=await Ec(i.path);t&&Object.assign(r.static.data,t.data)}),Dl(()=>{var i;r.hooks.hook("link:prefetch",async w=>{ws(w).protocol||await Ec(w)}),((i=navigator.connection)==null?void 0:i.effectiveType)!=="slow-2g"&&setTimeout(Ci,1e3)})}}),Fb=Sn(r=>{let i;async function w(){const t=await Ci();i&&clearTimeout(i),i=setTimeout(w,1e3*60*60);try{const x=await $fetch(Ml("builds/latest.json")+`?${Date.now()}`);x.id!==t.id&&r.hooks.callHook("app:manifest:update",x)}catch{}}Dl(()=>{i=setTimeout(w,1e3*60*60)})}),Nb=ht(()=>rt(()=>import("./Xli_fklN.js"),__vite__mapDeps([15,6,1,2,3,4,5,16,7,8]),import.meta.url).then(r=>r.default||r.default||r)),Ub=ht(()=>rt(()=>import("./t47rUjQB.js"),__vite__mapDeps([17,16,7,8,5,4]),import.meta.url).then(r=>r.default||r.default||r)),Bb=ht(()=>rt(()=>import("./CeHLcfh0.js"),__vite__mapDeps([18,7,5,8,4]),import.meta.url).then(r=>r.default||r.default||r)),Gb=ht(()=>rt(()=>import("./DSVbkqRh.js"),__vite__mapDeps([16,7,8,5,4]),import.meta.url).then(r=>r.default||r.default||r)),Vb=ht(()=>rt(()=>import("./B1tmNyhF.js"),__vite__mapDeps([6,1,2,3,4,5]),import.meta.url).then(r=>r.default||r.default||r)),Hb=ht(()=>rt(()=>import("./B16Ch1Rg.js"),__vite__mapDeps([19,1,2,3,4,5]),import.meta.url).then(r=>r.default||r.default||r)),zb=ht(()=>rt(()=>import("./3aFKPIgF.js"),__vite__mapDeps([20,3]),import.meta.url).then(r=>r.default||r.default||r)),Wb=ht(()=>rt(()=>import("./DbS0a68n.js"),[],import.meta.url).then(r=>r.default||r.default||r)),qb=ht(()=>rt(()=>import("./Bg6Wkwu9.js"),[],import.meta.url).then(r=>r.default||r.default||r)),Xb=ht(()=>rt(()=>import("./nVRvli7B.js"),__vite__mapDeps([21,20,3]),import.meta.url).then(r=>r.default||r.default||r)),Yb=ht(()=>rt(()=>import("./Dab_E90i.js"),__vite__mapDeps([22,23,24]),import.meta.url).then(r=>r.default||r.default||r)),$b=ht(()=>rt(()=>import("./wpwljwju.js"),[],import.meta.url).then(r=>r.default||r.default||r)),Zb=ht(()=>rt(()=>import("./DwoF_sus.js"),__vite__mapDeps([25,23,24]),import.meta.url).then(r=>r.default||r.default||r)),Kb=ht(()=>rt(()=>import("./BacZaOvF.js"),[],import.meta.url).then(r=>r.default||r.default||r)),Qb=ht(()=>rt(()=>import("./BsueCq5A.js"),[],import.meta.url).then(r=>r.default||r.default||r)),Jb=ht(()=>rt(()=>import("./PCdpkuPO.js"),[],import.meta.url).then(r=>r.default||r.default||r)),e1=ht(()=>rt(()=>import("./kCftLbeK.js"),[],import.meta.url).then(r=>r.default||r.default||r)),t1=ht(()=>rt(()=>import("./BUQkeXPm.js"),[],import.meta.url).then(r=>r.default||r.default||r)),r1=ht(()=>rt(()=>import("./D6go2xuX.js"),[],import.meta.url).then(r=>r.default||r.default||r)),n1=ht(()=>rt(()=>import("./CJD6qL-K.js"),[],import.meta.url).then(r=>r.default||r.default||r)),o1=ht(()=>rt(()=>import("./Ct3Jmt0b.js"),[],import.meta.url).then(r=>r.default||r.default||r)),s1=ht(()=>rt(()=>import("./BoZ9Gzu9.js"),[],import.meta.url).then(r=>r.default||r.default||r)),i1=ht(()=>rt(()=>import("./B25qHsMz.js"),[],import.meta.url).then(r=>r.default||r.default||r)),a1=ht(()=>rt(()=>import("./CReNMuyo.js"),[],import.meta.url).then(r=>r.default||r.default||r)),l1=ht(()=>rt(()=>import("./Dj_Dm3AU.js"),[],import.meta.url).then(r=>r.default||r.default||r)),u1=ht(()=>rt(()=>import("./BDlA7Zky.js"),[],import.meta.url).then(r=>r.default||r.default||r)),c1=ht(()=>rt(()=>import("./DK7GvCoQ.js"),[],import.meta.url).then(r=>r.default||r.default||r)),d1=ht(()=>rt(()=>import("./gYgHqO9f.js"),[],import.meta.url).then(r=>r.default||r.default||r)),f1=ht(()=>rt(()=>import("./BTZnUlcA.js"),[],import.meta.url).then(r=>r.default||r.default||r)),h1=ht(()=>rt(()=>import("./Bdjj16Wj.js"),[],import.meta.url).then(r=>r.default||r.default||r)),p1=ht(()=>rt(()=>import("./BvT8JnCb.js"),[],import.meta.url).then(r=>r.default||r.default||r)),m1=ht(()=>rt(()=>import("./Oa1zqAZH.js"),[],import.meta.url).then(r=>r.default||r.default||r)),y1=ht(()=>rt(()=>import("./B-Suu3Ve.js"),[],import.meta.url).then(r=>r.default||r.default||r)),g1=ht(()=>rt(()=>import("./eM-U89SY.js"),[],import.meta.url).then(r=>r.default||r.default||r)),v1=ht(()=>rt(()=>import("./DRhtvB_q.js"),[],import.meta.url).then(r=>r.default||r.default||r)),b1=ht(()=>rt(()=>import("./Dtl8qhH9.js"),[],import.meta.url).then(r=>r.default||r.default||r)),_1=[["ContentDoc",Nb],["ContentList",Ub],["ContentNavigation",Bb],["ContentQuery",Gb],["ContentRenderer",Vb],["ContentRendererMarkdown",Hb],["MDCSlot",zb],["DocumentDrivenEmpty",Wb],["DocumentDrivenNotFound",qb],["Markdown",Xb],["ProseCode",Yb],["ProseCodeInline",$b],["ProsePre",Zb],["ProseA",Kb],["ProseBlockquote",Qb],["ProseEm",Jb],["ProseH1",e1],["ProseH2",t1],["ProseH3",r1],["ProseH4",n1],["ProseH5",o1],["ProseH6",s1],["ProseHr",i1],["ProseImg",a1],["ProseLi",l1],["ProseOl",u1],["ProseP",c1],["ProseScript",d1],["ProseStrong",f1],["ProseTable",h1],["ProseTbody",p1],["ProseTd",m1],["ProseTh",y1],["ProseThead",g1],["ProseTr",v1],["ProseUl",b1]],w1=Sn({name:"nuxt:global-components",setup(r){for(const[i,w]of _1)r.vueApp.component(i,w),r.vueApp.component("Lazy"+i,w)}}),Fn={default:()=>rt(()=>import("./Zyr_YK_I.js"),[],import.meta.url).then(r=>r.default||r),empty:()=>rt(()=>import("./LT2DbrHy.js"),[],import.meta.url).then(r=>r.default||r),light:()=>rt(()=>import("./PIAawFjR.js"),[],import.meta.url).then(r=>r.default||r)},x1=Sn({name:"nuxt:prefetch",setup(r){const i=Xr();r.hooks.hook("app:mounted",()=>{i.beforeEach(async w=>{var x;const t=(x=w==null?void 0:w.meta)==null?void 0:x.layout;t&&typeof Fn[t]=="function"&&await Fn[t]()})}),r.hooks.hook("link:prefetch",w=>{if(jn(w))return;const t=i.resolve(w);if(!t)return;const x=t.meta.layout;let v=Il(t.meta.middleware);v=v.filter(s=>typeof s=="string");for(const s of v)typeof ts[s]=="function"&&ts[s]();x&&typeof Fn[x]=="function"&&Fn[x]()})}});function j1(r={}){const i=r.path||window.location.pathname;let w={};try{w=si(sessionStorage.getItem("nuxt:reload")||"{}")}catch{}if(r.force||(w==null?void 0:w.path)!==i||(w==null?void 0:w.expires){t.clear()}),r.hook("app:chunkError",({error:v})=>{t.add(v)});function x(v){const u="href"in v&&v.href[0]==="#"?w.app.baseURL+v.href:Si(w.app.baseURL,v.fullPath);j1({path:u,persistState:!0})}r.hook("app:manifest:update",()=>{i.beforeResolve(x)}),i.onError((v,s)=>{t.has(v)&&x(s)})}});var Vs=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function E1(r){return r&&r.__esModule&&Object.prototype.hasOwnProperty.call(r,"default")?r.default:r}function Hs(r){throw new Error('Could not dynamically require "'+r+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var Th={exports:{}};/*! p5.js v1.10.0 July 31, 2024 */(function(r,i){(function(w){r.exports=w()})(function(){var w;return function t(x,v,s){function u(g,m){if(!v[g]){if(!x[g]){var n=typeof Hs=="function"&&Hs;if(!m&&n)return n(g,!0);if(o)return o(g,!0);throw(m=new Error("Cannot find module '"+g+"'")).code="MODULE_NOT_FOUND",m}n=v[g]={exports:{}},x[g][0].call(n.exports,function(a){return u(x[g][1][a]||a)},n,n.exports,t,x,v,s)}return v[g].exports}for(var o=typeof Hs=="function"&&Hs,f=0;f>16&255,c[p++]=l>>8&255,c[p++]=255&l;return h===2&&(l=u[a.charCodeAt(d)]<<2|u[a.charCodeAt(d+1)]>>4,c[p++]=255&l),h===1&&(l=u[a.charCodeAt(d)]<<10|u[a.charCodeAt(d+1)]<<4|u[a.charCodeAt(d+2)]>>2,c[p++]=l>>8&255,c[p++]=255&l),c},v.fromByteArray=function(a){for(var l,d=a.length,y=d%3,h=[],c=0,p=d-y;c>18&63]+s[L>>12&63]+s[L>>6&63]+s[63&L]}(E));return k.join("")}(a,c,p>2]+s[l<<4&63]+"==")):y==2&&(l=(a[d-2]<<8)+a[d-1],h.push(s[l>>10]+s[l>>4&63]+s[l<<2&63]+"=")),h.join("")};for(var s=[],u=[],o=typeof Uint8Array<"u"?Uint8Array:Array,f="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",g=0,m=f.length;g>>1;case"base64":return H(T).length;default:if(Z)return q?-1:W(T).length;D=(""+D).toLowerCase(),Z=!0}}function p(T,D,G){var q,Z=!1;if((D=D===void 0||D<0?0:D)>this.length||(G=G===void 0||G>this.length?this.length:G)<=0||(G>>>=0)<=(D>>>=0))return"";for(T=T||"utf8";;)switch(T){case"hex":var ee=this,de=D,ne=G,$=ee.length;(!ne||ne<0||$=T.length){if(Z)return-1;G=T.length-1}else if(G<0){if(!Z)return-1;G=0}if(typeof D=="string"&&(D=n.from(D,q)),n.isBuffer(D))return D.length===0?-1:M(T,D,G,q,Z);if(typeof D=="number")return D&=255,typeof Uint8Array.prototype.indexOf=="function"?(Z?Uint8Array.prototype.indexOf:Uint8Array.prototype.lastIndexOf).call(T,D,G):M(T,[D],G,q,Z);throw new TypeError("val must be string, number or Buffer")}function M(T,D,G,q,Z){var ee=1,ne=T.length,ue=D.length;if(q!==void 0&&((q=String(q).toLowerCase())==="ucs2"||q==="ucs-2"||q==="utf16le"||q==="utf-16le")){if(T.length<2||D.length<2)return-1;ne/=ee=2,ue/=2,G/=2}function ie(ce,me){return ee===1?ce[me]:ce.readUInt16BE(me*ee)}if(Z)for(var he=-1,$=G;$>8,ue=ue%256,ie.push(ue),ie.push(ne);return ie}(D,T.length-G),T,G,q)}function O(T,D,G){G=Math.min(T.length,G);for(var q=[],Z=D;Z>>10&1023|55296),$=56320|1023&$),q.push($),Z+=z}var te=q,ce=te.length;if(ce<=L)return String.fromCharCode.apply(String,te);for(var me="",de=0;de"u"||typeof console.error!="function"||console.error("This browser lacks typed array (Uint8Array) support which is required by `buffer` v5.x. Use `buffer` v4.x if you require old browser support."),Object.defineProperty(n.prototype,"parent",{enumerable:!0,get:function(){if(n.isBuffer(this))return this.buffer}}),Object.defineProperty(n.prototype,"offset",{enumerable:!0,get:function(){if(n.isBuffer(this))return this.byteOffset}}),typeof Symbol<"u"&&Symbol.species!=null&&n[Symbol.species]===n&&Object.defineProperty(n,Symbol.species,{value:null,configurable:!0,enumerable:!1,writable:!1}),n.poolSize=8192,n.from=a,Object.setPrototypeOf(n.prototype,Uint8Array.prototype),Object.setPrototypeOf(n,Uint8Array),n.alloc=function(T,D,G){return D=D,G=G,l(T=T),!(T<=0)&&D!==void 0?typeof G=="string"?m(T).fill(D,G):m(T).fill(D):m(T)},n.allocUnsafe=d,n.allocUnsafeSlow=d,n.isBuffer=function(T){return T!=null&&T._isBuffer===!0&&T!==n.prototype},n.compare=function(T,D){if(K(T,Uint8Array)&&(T=n.from(T,T.offset,T.byteLength)),K(D,Uint8Array)&&(D=n.from(D,D.offset,D.byteLength)),!n.isBuffer(T)||!n.isBuffer(D))throw new TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array');if(T===D)return 0;for(var G=T.length,q=D.length,Z=0,ee=Math.min(G,q);ZT&&(D+=" ... "),""},f&&(n.prototype[f]=n.prototype.inspect),n.prototype.compare=function(T,D,G,q,Z){if(K(T,Uint8Array)&&(T=n.from(T,T.offset,T.byteLength)),!n.isBuffer(T))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof T);if(G===void 0&&(G=T?T.length:0),q===void 0&&(q=0),Z===void 0&&(Z=this.length),(D=D===void 0?0:D)<0||G>T.length||q<0||Z>this.length)throw new RangeError("out of range index");if(Z<=q&&G<=D)return 0;if(Z<=q)return-1;if(G<=D)return 1;if(this===T)return 0;for(var ee=(Z>>>=0)-(q>>>=0),ne=(G>>>=0)-(D>>>=0),ue=Math.min(ee,ne),ie=this.slice(q,Z),he=T.slice(D,G),$=0;$>>=0,isFinite(G)?(G>>>=0,q===void 0&&(q="utf8")):(q=G,G=void 0)}var Z=this.length-D;if((G===void 0||Zthis.length)throw new RangeError("Attempt to write outside buffer bounds");q=q||"utf8";for(var ee,ne,ue,ie=!1;;)switch(q){case"hex":var he=this,$=T,z=D,te=G,ce=(z=Number(z)||0,he.length-z);(!te||ce<(te=Number(te)))&&(te=ce),(ce=$.length)/2T.length)throw new RangeError("Index out of range")}function A(T,D,G,q){if(G+q>T.length)throw new RangeError("Index out of range");if(G<0)throw new RangeError("Index out of range")}function N(T,D,G,q,Z){return D=+D,G>>>=0,Z||A(T,0,G,4),o.write(T,D,G,q,23,4),G+4}function F(T,D,G,q,Z){return D=+D,G>>>=0,Z||A(T,0,G,8),o.write(T,D,G,q,52,8),G+8}n.prototype.slice=function(T,D){var G=this.length,G=((T=~~T)<0?(T+=G)<0&&(T=0):G>>=0,D>>>=0,G||C(T,D,this.length);for(var q=this[T],Z=1,ee=0;++ee>>=0,D>>>=0,G||C(T,D,this.length);for(var q=this[T+--D],Z=1;0>>=0,D||C(T,1,this.length),this[T]},n.prototype.readUInt16LE=function(T,D){return T>>>=0,D||C(T,2,this.length),this[T]|this[T+1]<<8},n.prototype.readUInt16BE=function(T,D){return T>>>=0,D||C(T,2,this.length),this[T]<<8|this[T+1]},n.prototype.readUInt32LE=function(T,D){return T>>>=0,D||C(T,4,this.length),(this[T]|this[T+1]<<8|this[T+2]<<16)+16777216*this[T+3]},n.prototype.readUInt32BE=function(T,D){return T>>>=0,D||C(T,4,this.length),16777216*this[T]+(this[T+1]<<16|this[T+2]<<8|this[T+3])},n.prototype.readIntLE=function(T,D,G){T>>>=0,D>>>=0,G||C(T,D,this.length);for(var q=this[T],Z=1,ee=0;++ee>>=0,D>>>=0,G||C(T,D,this.length);for(var q=D,Z=1,ee=this[T+--q];0>>=0,D||C(T,1,this.length),128&this[T]?-1*(255-this[T]+1):this[T]},n.prototype.readInt16LE=function(T,D){return T>>>=0,D||C(T,2,this.length),D=this[T]|this[T+1]<<8,32768&D?4294901760|D:D},n.prototype.readInt16BE=function(T,D){return T>>>=0,D||C(T,2,this.length),D=this[T+1]|this[T]<<8,32768&D?4294901760|D:D},n.prototype.readInt32LE=function(T,D){return T>>>=0,D||C(T,4,this.length),this[T]|this[T+1]<<8|this[T+2]<<16|this[T+3]<<24},n.prototype.readInt32BE=function(T,D){return T>>>=0,D||C(T,4,this.length),this[T]<<24|this[T+1]<<16|this[T+2]<<8|this[T+3]},n.prototype.readFloatLE=function(T,D){return T>>>=0,D||C(T,4,this.length),o.read(this,T,!0,23,4)},n.prototype.readFloatBE=function(T,D){return T>>>=0,D||C(T,4,this.length),o.read(this,T,!1,23,4)},n.prototype.readDoubleLE=function(T,D){return T>>>=0,D||C(T,8,this.length),o.read(this,T,!0,52,8)},n.prototype.readDoubleBE=function(T,D){return T>>>=0,D||C(T,8,this.length),o.read(this,T,!1,52,8)},n.prototype.writeUIntLE=function(T,D,G,q){T=+T,D>>>=0,G>>>=0,q||I(this,T,D,G,Math.pow(2,8*G)-1,0);var Z=1,ee=0;for(this[D]=255&T;++ee>>=0,G>>>=0,q||I(this,T,D,G,Math.pow(2,8*G)-1,0);var Z=G-1,ee=1;for(this[D+Z]=255&T;0<=--Z&&(ee*=256);)this[D+Z]=T/ee&255;return D+G},n.prototype.writeUInt8=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,1,255,0),this[D]=255&T,D+1},n.prototype.writeUInt16LE=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,2,65535,0),this[D]=255&T,this[D+1]=T>>>8,D+2},n.prototype.writeUInt16BE=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,2,65535,0),this[D]=T>>>8,this[D+1]=255&T,D+2},n.prototype.writeUInt32LE=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,4,4294967295,0),this[D+3]=T>>>24,this[D+2]=T>>>16,this[D+1]=T>>>8,this[D]=255&T,D+4},n.prototype.writeUInt32BE=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,4,4294967295,0),this[D]=T>>>24,this[D+1]=T>>>16,this[D+2]=T>>>8,this[D+3]=255&T,D+4},n.prototype.writeIntLE=function(T,D,G,q){T=+T,D>>>=0,q||I(this,T,D,G,(q=Math.pow(2,8*G-1))-1,-q);var Z=0,ee=1,ne=0;for(this[D]=255&T;++Z>0)-ne&255;return D+G},n.prototype.writeIntBE=function(T,D,G,q){T=+T,D>>>=0,q||I(this,T,D,G,(q=Math.pow(2,8*G-1))-1,-q);var Z=G-1,ee=1,ne=0;for(this[D+Z]=255&T;0<=--Z&&(ee*=256);)T<0&&ne===0&&this[D+Z+1]!==0&&(ne=1),this[D+Z]=(T/ee>>0)-ne&255;return D+G},n.prototype.writeInt8=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,1,127,-128),this[D]=255&(T=T<0?255+T+1:T),D+1},n.prototype.writeInt16LE=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,2,32767,-32768),this[D]=255&T,this[D+1]=T>>>8,D+2},n.prototype.writeInt16BE=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,2,32767,-32768),this[D]=T>>>8,this[D+1]=255&T,D+2},n.prototype.writeInt32LE=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,4,2147483647,-2147483648),this[D]=255&T,this[D+1]=T>>>8,this[D+2]=T>>>16,this[D+3]=T>>>24,D+4},n.prototype.writeInt32BE=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,4,2147483647,-2147483648),this[D]=(T=T<0?4294967295+T+1:T)>>>24,this[D+1]=T>>>16,this[D+2]=T>>>8,this[D+3]=255&T,D+4},n.prototype.writeFloatLE=function(T,D,G){return N(this,T,D,!0,G)},n.prototype.writeFloatBE=function(T,D,G){return N(this,T,D,!1,G)},n.prototype.writeDoubleLE=function(T,D,G){return F(this,T,D,!0,G)},n.prototype.writeDoubleBE=function(T,D,G){return F(this,T,D,!1,G)},n.prototype.copy=function(T,D,G,q){if(!n.isBuffer(T))throw new TypeError("argument should be a Buffer");if(G=G||0,q||q===0||(q=this.length),D>=T.length&&(D=T.length),(q=0=this.length)throw new RangeError("Index out of range");if(q<0)throw new RangeError("sourceEnd out of bounds");q>this.length&&(q=this.length);var Z=(q=T.length-D>>=0,G=G===void 0?this.length:G>>>0,typeof(T=T||0)=="number")for(ee=D;ee>6|192,63&G|128)}else if(G<65536){if((D-=3)<0)break;ee.push(G>>12|224,G>>6&63|128,63&G|128)}else{if(!(G<1114112))throw new Error("Invalid code point");if((D-=4)<0)break;ee.push(G>>18|240,G>>12&63|128,G>>6&63|128,63&G|128)}}return ee}function H(T){return u.toByteArray(function(D){if((D=(D=D.split("=")[0]).trim().replace(B,"")).length<2)return"";for(;D.length%4!=0;)D+="=";return D}(T))}function V(T,D,G,q){for(var Z=0;Z=D.length||Z>=T.length);++Z)D[Z+G]=T[Z];return Z}function K(T,D){return T instanceof D||T!=null&&T.constructor!=null&&T.constructor.name!=null&&T.constructor.name===D.name}function J(T){return T!=T}var le=function(){for(var T="0123456789abcdef",D=new Array(256),G=0;G<16;++G)for(var q=16*G,Z=0;Z<16;++Z)D[q+Z]=T[G]+T[Z];return D}()}).call(this,t("buffer").Buffer)},{"base64-js":1,buffer:4,ieee754:254}],5:[function(t,x,v){x.exports=function(s){if(typeof s!="function")throw TypeError(String(s)+" is not a function");return s}},{}],6:[function(t,x,v){var s=t("../internals/is-object");x.exports=function(u){if(s(u)||u===null)return u;throw TypeError("Can't set "+String(u)+" as a prototype")}},{"../internals/is-object":75}],7:[function(o,x,v){var s=o("../internals/well-known-symbol"),u=o("../internals/object-create"),o=o("../internals/object-define-property"),f=s("unscopables"),g=Array.prototype;g[f]==null&&o.f(g,f,{configurable:!0,value:u(null)}),x.exports=function(m){g[f][m]=!0}},{"../internals/object-create":91,"../internals/object-define-property":93,"../internals/well-known-symbol":150}],8:[function(t,x,v){var s=t("../internals/string-multibyte").charAt;x.exports=function(u,o,f){return o+(f?s(u,o).length:1)}},{"../internals/string-multibyte":125}],9:[function(t,x,v){x.exports=function(s,u,o){if(s instanceof u)return s;throw TypeError("Incorrect "+(o?o+" ":"")+"invocation")}},{}],10:[function(t,x,v){var s=t("../internals/is-object");x.exports=function(u){if(s(u))return u;throw TypeError(String(u)+" is not an object")}},{"../internals/is-object":75}],11:[function(t,x,v){x.exports=typeof ArrayBuffer<"u"&&typeof DataView<"u"},{}],12:[function(A,x,v){function s(F){return m(F)&&n(N,a(F))}var u,o=A("../internals/array-buffer-native"),f=A("../internals/descriptors"),g=A("../internals/global"),m=A("../internals/is-object"),n=A("../internals/has"),a=A("../internals/classof"),l=A("../internals/create-non-enumerable-property"),d=A("../internals/redefine"),y=A("../internals/object-define-property").f,h=A("../internals/object-get-prototype-of"),c=A("../internals/object-set-prototype-of"),L=A("../internals/well-known-symbol"),A=A("../internals/uid"),p=g.Int8Array,b=p&&p.prototype,j=g.Uint8ClampedArray,j=j&&j.prototype,M=p&&h(p),E=b&&h(b),k=Object.prototype,O=k.isPrototypeOf,L=L("toStringTag"),C=A("TYPED_ARRAY_TAG"),I=o&&!!c&&a(g.opera)!=="Opera",A=!1,N={Int8Array:1,Uint8Array:1,Uint8ClampedArray:1,Int16Array:2,Uint16Array:2,Int32Array:4,Uint32Array:4,Float32Array:4,Float64Array:8};for(u in N)g[u]||(I=!1);if((!I||typeof M!="function"||M===Function.prototype)&&(M=function(){throw TypeError("Incorrect invocation")},I))for(u in N)g[u]&&c(g[u],M);if((!I||!E||E===k)&&(E=M.prototype,I))for(u in N)g[u]&&c(g[u].prototype,E);if(I&&h(j)!==E&&c(j,E),f&&!n(E,L))for(u in A=!0,y(E,L,{get:function(){return m(this)?this[C]:void 0}}),N)g[u]&&l(g[u],C,u);x.exports={NATIVE_ARRAY_BUFFER_VIEWS:I,TYPED_ARRAY_TAG:A&&C,aTypedArray:function(F){if(s(F))return F;throw TypeError("Target is not a typed array")},aTypedArrayConstructor:function(F){if(c){if(O.call(M,F))return F}else for(var B in N)if(n(N,u)&&(B=g[B],B&&(F===B||O.call(B,F))))return F;throw TypeError("Target is not a typed array constructor")},exportTypedArrayMethod:function(F,B,W){if(f){if(W)for(var H in N)H=g[H],H&&n(H.prototype,F)&&delete H.prototype[F];E[F]&&!W||d(E,F,!W&&I&&b[F]||B)}},exportTypedArrayStaticMethod:function(F,B,W){var H,V;if(f){if(c){if(W)for(H in N)(V=g[H])&&n(V,F)&&delete V[F];if(M[F]&&!W)return;try{return d(M,F,!W&&I&&p[F]||B)}catch{}}for(H in N)!(V=g[H])||V[F]&&!W||d(V,F,B)}},isView:function(F){return F=a(F),F==="DataView"||n(N,F)},isTypedArray:s,TypedArray:M,TypedArrayPrototype:E}},{"../internals/array-buffer-native":11,"../internals/classof":29,"../internals/create-non-enumerable-property":38,"../internals/descriptors":43,"../internals/global":60,"../internals/has":61,"../internals/is-object":75,"../internals/object-define-property":93,"../internals/object-get-prototype-of":98,"../internals/object-set-prototype-of":102,"../internals/redefine":110,"../internals/uid":147,"../internals/well-known-symbol":150}],13:[function(G,x,v){function s(z){return[255&z]}function u(z){return[255&z,z>>8&255]}function o(z){return[255&z,z>>8&255,z>>16&255,z>>24&255]}function f(z){return z[3]<<24|z[2]<<16|z[1]<<8|z[0]}function g(z){return ee(z,23,4)}function m(z){return ee(z,52,8)}function n(z,te){A(z[K],te,{get:function(){return B(this)[te]}})}function a(ve,te,ye,me){if(ye=k(ye),ve=B(ve),ye+te>ve.byteLength)throw Z(J);var de=B(ve.buffer).bytes,ye=ye+ve.byteOffset,ve=de.slice(ye,ye+te);return me?ve:ve.reverse()}function l(z,te,ce,me,de,ye){if(ce=k(ce),z=B(z),ce+te>z.byteLength)throw Z(J);for(var ve=B(z.buffer).bytes,ke=ce+z.byteOffset,be=me(+de),Ne=0;Nehe;)(ue=ie[he++])in T||c(T,ue,le[ue]);d.constructor=T}C&&L(G)!==q&&C(G,q);var O=new D(new T(2)),$=G.setInt8;O.setInt8(0,2147483648),O.setInt8(1,2147483649),!O.getInt8(0)&&O.getInt8(1)||p(G,{setInt8:function(te,ce){$.call(this,te,ce<<24>>24)},setUint8:function(te,ce){$.call(this,te,ce<<24>>24)}},{unsafe:!0})}else T=function(z){j(this,T,H),z=k(z),W(this,{bytes:N.call(new Array(z),0),byteLength:z}),y||(this.byteLength=z)},D=function(z,de,ce){j(this,D,V),j(z,T,V);var me=B(z).byteLength,de=M(de);if(de<0||me>24},getUint8:function(z){return a(this,1,z)[0]},getInt16:function(z){return z=a(this,2,z,1>16},getUint16:function(z){return z=a(this,2,z,1>>0},getFloat32:function(z){return ne(a(this,4,z,1"+n+""}},{"../internals/require-object-coercible":115}],37:[function(t,x,v){function s(){return this}var u=t("../internals/iterators-core").IteratorPrototype,o=t("../internals/object-create"),f=t("../internals/create-property-descriptor"),g=t("../internals/set-to-string-tag"),m=t("../internals/iterators");x.exports=function(n,a,l){return a+=" Iterator",n.prototype=o(u,{next:f(1,l)}),g(n,a,!1,!0),m[a]=s,n}},{"../internals/create-property-descriptor":39,"../internals/iterators":80,"../internals/iterators-core":79,"../internals/object-create":91,"../internals/set-to-string-tag":119}],38:[function(t,x,v){var s=t("../internals/descriptors"),u=t("../internals/object-define-property"),o=t("../internals/create-property-descriptor");x.exports=s?function(f,g,m){return u.f(f,g,o(1,m))}:function(f,g,m){return f[g]=m,f}},{"../internals/create-property-descriptor":39,"../internals/descriptors":43,"../internals/object-define-property":93}],39:[function(t,x,v){x.exports=function(s,u){return{enumerable:!(1&s),configurable:!(2&s),writable:!(4&s),value:u}}},{}],40:[function(t,x,v){var s=t("../internals/to-primitive"),u=t("../internals/object-define-property"),o=t("../internals/create-property-descriptor");x.exports=function(f,g,m){g=s(g),g in f?u.f(f,g,o(0,m)):f[g]=m}},{"../internals/create-property-descriptor":39,"../internals/object-define-property":93,"../internals/to-primitive":142}],41:[function(h,x,v){function s(){return this}var u=h("../internals/export"),o=h("../internals/create-iterator-constructor"),f=h("../internals/object-get-prototype-of"),g=h("../internals/object-set-prototype-of"),m=h("../internals/set-to-string-tag"),n=h("../internals/create-non-enumerable-property"),a=h("../internals/redefine"),l=h("../internals/well-known-symbol"),d=h("../internals/is-pure"),y=h("../internals/iterators"),h=h("../internals/iterators-core"),c=h.IteratorPrototype,p=h.BUGGY_SAFARI_ITERATORS,b=l("iterator"),j="values",M="entries";x.exports=function(E,k,O,W,C,I,A){o(O,k,W);function N(T){if(T===C&&J)return J;if(!p&&T in V)return V[T];switch(T){case"keys":case j:case M:return function(){return new O(this,T)}}return function(){return new O(this)}}var F,B,W=k+" Iterator",H=!1,V=E.prototype,K=V[b]||V["@@iterator"]||C&&V[C],J=!p&&K||N(C),le=k=="Array"&&V.entries||K;if(le&&(le=f(le.call(new E)),c!==Object.prototype&&le.next&&(d||f(le)===c||(g?g(le,c):typeof le[b]!="function"&&n(le,b,s)),m(le,W,!0,!0),d&&(y[W]=s))),C==j&&K&&K.name!==j&&(H=!0,J=function(){return K.call(this)}),d&&!A||V[b]===J||n(V,b,J),y[k]=J,C)if(F={values:N(j),keys:I?J:N("keys"),entries:N(M)},A)for(B in F)!p&&!H&&B in V||a(V,B,F[B]);else u({target:k,proto:!0,forced:p||H},F);return F}},{"../internals/create-iterator-constructor":37,"../internals/create-non-enumerable-property":38,"../internals/export":50,"../internals/is-pure":76,"../internals/iterators":80,"../internals/iterators-core":79,"../internals/object-get-prototype-of":98,"../internals/object-set-prototype-of":102,"../internals/redefine":110,"../internals/set-to-string-tag":119,"../internals/well-known-symbol":150}],42:[function(t,x,v){var s=t("../internals/path"),u=t("../internals/has"),o=t("../internals/well-known-symbol-wrapped"),f=t("../internals/object-define-property").f;x.exports=function(g){var m=s.Symbol||(s.Symbol={});u(m,g)||f(m,g,{value:o.f(g)})}},{"../internals/has":61,"../internals/object-define-property":93,"../internals/path":106,"../internals/well-known-symbol-wrapped":149}],43:[function(t,x,v){t=t("../internals/fails"),x.exports=!t(function(){return Object.defineProperty({},1,{get:function(){return 7}})[1]!=7})},{"../internals/fails":51}],44:[function(u,x,v){var s=u("../internals/global"),u=u("../internals/is-object"),o=s.document,f=u(o)&&u(o.createElement);x.exports=function(g){return f?o.createElement(g):{}}},{"../internals/global":60,"../internals/is-object":75}],45:[function(t,x,v){x.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},{}],46:[function(t,x,v){t=t("../internals/engine-user-agent"),x.exports=/(iphone|ipod|ipad).*applewebkit/i.test(t)},{"../internals/engine-user-agent":47}],47:[function(t,x,v){t=t("../internals/get-built-in"),x.exports=t("navigator","userAgent")||""},{"../internals/get-built-in":57}],48:[function(o,x,v){var s,u,f=o("../internals/global"),o=o("../internals/engine-user-agent"),f=f.process,f=f&&f.versions,f=f&&f.v8;f?u=(s=f.split("."))[0]+s[1]:o&&(!(s=o.match(/Edge\/(\d+)/))||74<=s[1])&&(s=o.match(/Chrome\/(\d+)/))&&(u=s[1]),x.exports=u&&+u},{"../internals/engine-user-agent":47,"../internals/global":60}],49:[function(t,x,v){x.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},{}],50:[function(t,x,v){var s=t("../internals/global"),u=t("../internals/object-get-own-property-descriptor").f,o=t("../internals/create-non-enumerable-property"),f=t("../internals/redefine"),g=t("../internals/set-global"),m=t("../internals/copy-constructor-properties"),n=t("../internals/is-forced");x.exports=function(a,l){var d,y,h,c=a.target,p=a.global,b=a.stat,j=p?s:b?s[c]||g(c,{}):(s[c]||{}).prototype;if(j)for(d in l){if(y=l[d],h=a.noTargetGet?(h=u(j,d))&&h.value:j[d],!n(p?d:c+(b?".":"#")+d,a.forced)&&h!==void 0){if(typeof y==typeof h)continue;m(y,h)}(a.sham||h&&h.sham)&&o(y,"sham",!0),f(j,d,y,a)}}},{"../internals/copy-constructor-properties":33,"../internals/create-non-enumerable-property":38,"../internals/global":60,"../internals/is-forced":74,"../internals/object-get-own-property-descriptor":94,"../internals/redefine":110,"../internals/set-global":117}],51:[function(t,x,v){x.exports=function(s){try{return!!s()}catch{return!0}}},{}],52:[function(l,x,v){l("../modules/es.regexp.exec");var s=l("../internals/redefine"),u=l("../internals/fails"),o=l("../internals/well-known-symbol"),f=l("../internals/regexp-exec"),g=l("../internals/create-non-enumerable-property"),m=o("species"),n=!u(function(){var h=/./;return h.exec=function(){var c=[];return c.groups={a:"7"},c},"".replace(h,"$")!=="7"}),a="a".replace(/./,"$0")==="$0",l=o("replace"),d=!!/./[l]&&/./[l]("a","$0")==="",y=!u(function(){var c=/(?:)/,h=c.exec,c=(c.exec=function(){return h.apply(this,arguments)},"ab".split(c));return c.length!==2||c[0]!=="a"||c[1]!=="b"});x.exports=function(h,c,p,b){var j,M,E=o(h),k=!u(function(){var L={};return L[E]=function(){return 7},""[h](L)!=7}),O=k&&!u(function(){var L=!1,C=/a/;return h==="split"&&((C={constructor:{}}).constructor[m]=function(){return C},C.flags="",C[E]=/./[E]),C.exec=function(){return L=!0,null},C[E](""),!L});k&&O&&(h!=="replace"||n&&a&&!d)&&(h!=="split"||y)||(j=/./[E],p=(O=p(E,""[h],function(L,C,I,A,N){return C.exec===f?k&&!N?{done:!0,value:j.call(C,I,A)}:{done:!0,value:L.call(I,C,A)}:{done:!1}},{REPLACE_KEEPS_$0:a,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:d}))[0],M=O[1],s(String.prototype,h,p),s(RegExp.prototype,E,c==2?function(L,C){return M.call(L,this,C)}:function(L){return M.call(L,this)})),b&&g(RegExp.prototype[E],"sham",!0)}},{"../internals/create-non-enumerable-property":38,"../internals/fails":51,"../internals/redefine":110,"../internals/regexp-exec":112,"../internals/well-known-symbol":150,"../modules/es.regexp.exec":195}],53:[function(t,x,v){function s(g,m,n,a,l,d,y,h){for(var c,p=l,b=0,j=!!y&&f(y,h,3);b>1,j=n===23?u(2,-24)-u(2,-77):0,M=m<0||m===0&&1/m<0?1:0,E=0;for((m=s(m))!=m||m===1/0?(d=m!=m?1:0,l=p):(l=o(f(m)/g),m*(y=u(2,-l))<1&&(l--,y*=2),2<=(m+=1<=l+b?j/y:j*u(2,1-b))*y&&(l++,y/=2),p<=l+b?(d=0,l=p):1<=l+b?(d=(m*y-1)*u(2,n),l+=b):(d=m*u(2,b-1)*u(2,n),l=0));8<=n;h[E++]=255&d,d/=256,n-=8);for(l=l<>1,h=p-7,c=l-1,p=m[c--],b=127&p;for(p>>=7;0>=-h,h+=n;0"+b+""},p=function(){try{u=document.domain&&new ActiveXObject("htmlfile")}catch{}p=u?((b=u).write(c("")),b.close(),j=b.parentWindow.Object,b=null,j):(b=a("iframe"),j="java"+y+":",b.style.display="none",n.appendChild(b),b.src=String(j),(j=b.contentWindow.document).open(),j.write(c("document.F=Object")),j.close(),j.F);for(var b,j,M=g.length;M--;)delete p[d][g[M]];return p()};m[h]=!0,x.exports=Object.create||function(b,j){var M;return b!==null?(s[d]=o(b),M=new s,s[d]=null,M[h]=b):M=p(),j===void 0?M:f(M,j)}},{"../internals/an-object":10,"../internals/document-create-element":44,"../internals/enum-bug-keys":49,"../internals/hidden-keys":62,"../internals/html":64,"../internals/object-define-properties":92,"../internals/shared-key":120}],92:[function(t,x,v){var s=t("../internals/descriptors"),u=t("../internals/object-define-property"),o=t("../internals/an-object"),f=t("../internals/object-keys");x.exports=s?Object.defineProperties:function(g,m){o(g);for(var n,a=f(m),l=a.length,d=0;dl;)!s(a,n=m[l++])||~o(d,n)||d.push(n);return d}},{"../internals/array-includes":18,"../internals/has":61,"../internals/hidden-keys":62,"../internals/to-indexed-object":136}],100:[function(t,x,v){var s=t("../internals/object-keys-internal"),u=t("../internals/enum-bug-keys");x.exports=Object.keys||function(o){return s(o,u)}},{"../internals/enum-bug-keys":49,"../internals/object-keys-internal":99}],101:[function(t,x,v){var s={}.propertyIsEnumerable,u=Object.getOwnPropertyDescriptor,o=u&&!s.call({1:2},1);v.f=o?function(f){return f=u(this,f),!!f&&f.enumerable}:s},{}],102:[function(t,x,v){var s=t("../internals/an-object"),u=t("../internals/a-possible-prototype");x.exports=Object.setPrototypeOf||("__proto__"in{}?function(){var o,f=!1,g={};try{(o=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set).call(g,[]),f=g instanceof Array}catch{}return function(m,n){return s(m),u(n),f?o.call(m,n):m.__proto__=n,m}}():void 0)},{"../internals/a-possible-prototype":6,"../internals/an-object":10}],103:[function(t,x,v){function s(m){return function(n){for(var a,l=f(n),d=o(l),y=d.length,h=0,c=[];hc&&(y=y.slice(0,c)),m?d+y:y+d)}}var u=t("../internals/to-length"),o=t("../internals/string-repeat"),f=t("../internals/require-object-coercible"),g=Math.ceil;x.exports={start:s(!1),end:s(!0)}},{"../internals/require-object-coercible":115,"../internals/string-repeat":129,"../internals/to-length":138}],128:[function(t,x,v){function s(p){return p+22+75*(p<26)}function u(p){var b,j=[],M=(p=function(K){for(var J=[],le=0,T=K.length;leh((o-k)/N))throw RangeError(d);for(k+=(I-E)*N,E=I,A=0;Ao)throw RangeError(d);if(b==E){for(var F=k,B=f;;B+=f){var W=B<=O?1:O+g<=B?g:B-O;if(F>1,K+=h(K/J);y*g>>1>>=1)&&(f+=f))1&m&&(g+=f);return g}},{"../internals/require-object-coercible":115,"../internals/to-integer":137}],130:[function(t,x,v){var s=t("../internals/fails"),u=t("../internals/whitespaces");x.exports=function(o){return s(function(){return!!u[o]()||"​…᠎"[o]()!="​…᠎"||u[o].name!==o})}},{"../internals/fails":51,"../internals/whitespaces":151}],131:[function(o,x,v){function s(m){return function(n){return n=String(u(n)),1&m&&(n=n.replace(f,"")),n=2&m?n.replace(g,""):n}}var u=o("../internals/require-object-coercible"),o="["+o("../internals/whitespaces")+"]",f=RegExp("^"+o+o+"*"),g=RegExp(o+o+"*$");x.exports={start:s(1),end:s(2),trim:s(3)}},{"../internals/require-object-coercible":115,"../internals/whitespaces":151}],132:[function(y,x,v){function s(C){return function(){L(C)}}function u(C){L(C.data)}function o(C){g.postMessage(C+"",h.protocol+"//"+h.host)}var f,g=y("../internals/global"),m=y("../internals/fails"),n=y("../internals/classof-raw"),a=y("../internals/function-bind-context"),l=y("../internals/html"),d=y("../internals/document-create-element"),y=y("../internals/engine-is-ios"),h=g.location,c=g.setImmediate,p=g.clearImmediate,b=g.process,j=g.MessageChannel,M=g.Dispatch,E=0,k={},O="onreadystatechange",L=function(C){var I;k.hasOwnProperty(C)&&(I=k[C],delete k[C],I())};c&&p||(c=function(C){for(var I=[],A=1;A=d.length?{value:l.target=void 0,done:!0}:y=="keys"?{value:h,done:!1}:y=="values"?{value:d[h],done:!1}:{value:[h,d[h]],done:!1}},"values"),o.Arguments=o.Array,u("keys"),u("values"),u("entries")},{"../internals/add-to-unscopables":7,"../internals/define-iterator":41,"../internals/internal-state":71,"../internals/iterators":80,"../internals/to-indexed-object":136}],166:[function(g,x,v){var s=g("../internals/export"),f=g("../internals/indexed-object"),u=g("../internals/to-indexed-object"),g=g("../internals/array-method-is-strict"),o=[].join,f=f!=Object,g=g("join",",");s({target:"Array",proto:!0,forced:f||!g},{join:function(m){return o.call(u(this),m===void 0?",":m)}})},{"../internals/array-method-is-strict":22,"../internals/export":50,"../internals/indexed-object":67,"../internals/to-indexed-object":136}],167:[function(u,x,v){var s=u("../internals/export"),u=u("../internals/array-last-index-of");s({target:"Array",proto:!0,forced:u!==[].lastIndexOf},{lastIndexOf:u})},{"../internals/array-last-index-of":20,"../internals/export":50}],168:[function(f,x,v){var s=f("../internals/export"),u=f("../internals/array-iteration").map,o=f("../internals/array-method-has-species-support"),f=f("../internals/array-method-uses-to-length"),o=o("map"),f=f("map");s({target:"Array",proto:!0,forced:!o||!f},{map:function(g){return u(this,g,1I;I++)m(M,O=C[I])&&!m(L,O)&&p(L,O,c(M,O));(L.prototype=E).constructor=L,g(o,j,L)}},{"../internals/classof-raw":28,"../internals/descriptors":43,"../internals/fails":51,"../internals/global":60,"../internals/has":61,"../internals/inherit-if-required":68,"../internals/is-forced":74,"../internals/object-create":91,"../internals/object-define-property":93,"../internals/object-get-own-property-descriptor":94,"../internals/object-get-own-property-names":96,"../internals/redefine":110,"../internals/string-trim":131,"../internals/to-primitive":142}],180:[function(t,x,v){t("../internals/export")({target:"Number",stat:!0},{EPSILON:Math.pow(2,-52)})},{"../internals/export":50}],181:[function(t,x,v){t("../internals/export")({target:"Number",stat:!0},{isFinite:t("../internals/number-is-finite")})},{"../internals/export":50,"../internals/number-is-finite":89}],182:[function(m,x,v){function s(l,d,y){return d===0?y:d%2==1?s(l,d-1,y*l):s(l*l,d/2,y)}var u=m("../internals/export"),o=m("../internals/to-integer"),f=m("../internals/this-number-value"),g=m("../internals/string-repeat"),m=m("../internals/fails"),n=1 .toFixed,a=Math.floor;u({target:"Number",proto:!0,forced:n&&(8e-5.toFixed(3)!=="0.000"||.9.toFixed(0)!=="1"||1.255.toFixed(2)!=="1.25"||0xde0b6b3a7640080.toFixed(0)!=="1000000000000000128")||!m(function(){n.call({})})},{toFixed:function(j){function d(O,L){for(var C=-1,I=L;++C<6;)I+=O*M[C],M[C]=I%1e7,I=a(I/1e7)}function y(O){for(var L=6,C=0;0<=--L;)C+=M[L],M[L]=a(C/O),C=C%O*1e7}function h(){for(var O,L=6,C="";0<=--L;)C===""&&L!==0&&M[L]===0||(O=String(M[L]),C=C===""?O:C+g.call("0",7-O.length)+O);return C}var c,p,b=f(this),j=o(j),M=[0,0,0,0,0,0],E="",k="0";if(j<0||20Pe;){var He,We,qe,Ye=se[Pe++],lt=Se?Ye.ok:Ye.fail,ot=Ye.resolve,Ke=Ye.reject,it=Ye.domain;try{lt?(Se||(Ee.rejection===ye&&function(nt,Ct){C.call(n,function(){he?ee.emit("rejectionHandled",nt):Re(te,nt,Ct.value)})}(Le,Ee),Ee.rejection=de),lt===!0?He=we:(it&&it.enter(),He=lt(we),it&&(it.exit(),qe=!0)),He===Ye.promise?Ke(q("Promise-chain cycle")):(We=be(He))?We.call(He,ot,Ke):ot(He)):Ke(we)}catch(nt){it&&!qe&&it.exit(),Ke(nt)}}Ee.reactions=[],Ee.notified=!1,re&&!Ee.rejection&&(Q=Le,ae=Ee,C.call(n,function(){var nt=ae.value,Ct=Ie(ae);if(Ct&&(Ct=B(function(){he?ee.emit("unhandledRejection",nt,Q):Re(z,Q,nt)}),ae.rejection=he||Ie(ae)?ye:de,Ct.error))throw Ct.value}))}))},Re=function(Le,Ee,re){var se;$?((se=Z.createEvent("Event")).promise=Ee,se.reason=re,se.initEvent(Le,!1,!0),n.dispatchEvent(se)):se={promise:Ee,reason:re},(Ee=n["on"+Le])?Ee(se):Le===z&&N("Unhandled promise rejection",re)},Ie=function(Le){return Le.rejection!==de&&!Le.parent},Fe=function(Le,Ee,re,se){return function(Q){Le(Ee,re,Q,se)}},Ge=function(Le,Ee,re,se){Ee.done||(Ee.done=!0,(Ee=se||Ee).value=re,Ee.state=me,Ne(Le,Ee,!0))},xe=function(Le,Ee,re,se){if(!Ee.done){Ee.done=!0,se&&(Ee=se);try{if(Le===re)throw q("Promise can't be resolved itself");var Q=be(re);Q?I(function(){var ae={done:!1};try{Q.call(re,Fe(xe,Le,ae,Ee),Fe(Ge,Le,ae,Ee))}catch(we){Ge(Le,ae,we,Ee)}}):(Ee.value=re,Ee.state=ce,Ne(Le,Ee,!1))}catch(ae){Ge(Le,{done:!1},ae,Ee)}}};ve&&(G=function(Le){j(this,G,J),b(Le),s.call(this);var Ee=le(this);try{Le(Fe(xe,this,Ee),Fe(Ge,this,Ee))}catch(re){Ge(this,Ee,re)}},(s=function(Le){T(this,{type:J,done:!1,notified:!1,parent:!1,reactions:[],rejection:!1,state:0,value:void 0})}).prototype=y(G.prototype,{then:function(Le,Ee){var re=D(this),se=ue(L(this,G));return se.ok=typeof Le!="function"||Le,se.fail=typeof Ee=="function"&&Ee,se.domain=he?ee.domain:void 0,re.parent=!0,re.reactions.push(se),re.state!=0&&Ne(this,re,!1),se.promise},catch:function(Le){return this.then(void 0,Le)}}),u=function(){var Le=new s,Ee=le(Le);this.promise=Le,this.resolve=Fe(xe,Le,Ee),this.reject=Fe(Ge,Le,Ee)},F.f=ue=function(Le){return Le===G||Le===o?new u:ie(Le)},m||typeof l!="function"||(f=l.prototype.then,d(l.prototype,"then",function(Le,Ee){var re=this;return new G(function(se,Q){f.call(re,se,Q)}).then(Le,Ee)},{unsafe:!0}),typeof ne=="function"&&g({global:!0,enumerable:!0,forced:!0},{fetch:function(Le){return A(G,ne.apply(n,arguments))}}))),g({global:!0,wrap:!0,forced:ve},{Promise:G}),h(G,J,!1,!0),c(J),o=a(J),g({target:J,stat:!0,forced:ve},{reject:function(Le){var Ee=ue(this);return Ee.reject.call(void 0,Le),Ee.promise}}),g({target:J,stat:!0,forced:m||ve},{resolve:function(Le){return A(m&&this===o?G:this,Le)}}),g({target:J,stat:!0,forced:ke},{all:function(Le){var Ee=this,re=ue(Ee),se=re.resolve,Q=re.reject,ae=B(function(){var we=b(Ee.resolve),Se=[],Pe=0,He=1;k(Le,function(We){var qe=Pe++,Ye=!1;Se.push(void 0),He++,we.call(Ee,We).then(function(lt){Ye||(Ye=!0,Se[qe]=lt,--He||se(Se))},Q)}),--He||se(Se)});return ae.error&&Q(ae.value),re.promise},race:function(Le){var Ee=this,re=ue(Ee),se=re.reject,Q=B(function(){var ae=b(Ee.resolve);k(Le,function(we){ae.call(Ee,we).then(re.resolve,se)})});return Q.error&&se(Q.value),re.promise}})},{"../internals/a-function":5,"../internals/an-instance":9,"../internals/check-correctness-of-iteration":27,"../internals/classof-raw":28,"../internals/engine-v8-version":48,"../internals/export":50,"../internals/get-built-in":57,"../internals/global":60,"../internals/host-report-errors":63,"../internals/inspect-source":69,"../internals/internal-state":71,"../internals/is-forced":74,"../internals/is-object":75,"../internals/is-pure":76,"../internals/iterate":78,"../internals/microtask":82,"../internals/native-promise-constructor":83,"../internals/new-promise-capability":87,"../internals/perform":107,"../internals/promise-resolve":108,"../internals/redefine":110,"../internals/redefine-all":109,"../internals/set-species":118,"../internals/set-to-string-tag":119,"../internals/species-constructor":123,"../internals/task":132,"../internals/well-known-symbol":150}],192:[function(n,x,v){var s=n("../internals/export"),y=n("../internals/get-built-in"),u=n("../internals/a-function"),o=n("../internals/an-object"),f=n("../internals/is-object"),g=n("../internals/object-create"),m=n("../internals/function-bind"),n=n("../internals/fails"),a=y("Reflect","construct"),l=n(function(){function h(){}return!(a(function(){},[],h)instanceof h)}),d=!n(function(){a(function(){})}),y=l||d;s({target:"Reflect",stat:!0,forced:y,sham:y},{construct:function(h,c){u(h),o(c);var p=arguments.length<3?h:u(arguments[2]);if(d&&!l)return a(h,c,p);if(h==p){switch(c.length){case 0:return new h;case 1:return new h(c[0]);case 2:return new h(c[0],c[1]);case 3:return new h(c[0],c[1],c[2]);case 4:return new h(c[0],c[1],c[2],c[3])}var b=[null];return b.push.apply(b,c),new(m.apply(h,b))}return b=p.prototype,p=g(f(b)?b:Object.prototype),b=Function.apply.call(h,p,c),f(b)?b:p}})},{"../internals/a-function":5,"../internals/an-object":10,"../internals/export":50,"../internals/fails":51,"../internals/function-bind":56,"../internals/get-built-in":57,"../internals/is-object":75,"../internals/object-create":91}],193:[function(t,x,v){var s=t("../internals/export"),u=t("../internals/is-object"),o=t("../internals/an-object"),f=t("../internals/has"),g=t("../internals/object-get-own-property-descriptor"),m=t("../internals/object-get-prototype-of");s({target:"Reflect",stat:!0},{get:function n(a,l){var d,y=arguments.length<3?a:arguments[2];return o(a)===y?a[l]:(d=g.f(a,l))?f(d,"value")?d.value:d.get===void 0?void 0:d.get.call(y):u(d=m(a))?n(d,l,y):void 0}})},{"../internals/an-object":10,"../internals/export":50,"../internals/has":61,"../internals/is-object":75,"../internals/object-get-own-property-descriptor":94,"../internals/object-get-prototype-of":98}],194:[function(t,x,v){var s=t("../internals/descriptors"),u=t("../internals/global"),o=t("../internals/is-forced"),f=t("../internals/inherit-if-required"),g=t("../internals/object-define-property").f,m=t("../internals/object-get-own-property-names").f,n=t("../internals/is-regexp"),a=t("../internals/regexp-flags"),l=t("../internals/regexp-sticky-helpers"),d=t("../internals/redefine"),y=t("../internals/fails"),h=t("../internals/internal-state").set,c=t("../internals/set-species"),p=t("../internals/well-known-symbol")("match"),b=u.RegExp,j=b.prototype,M=/a/g,E=/a/g,k=new b(M)!==M,O=l.UNSUPPORTED_Y;if(s&&o("RegExp",!k||O||y(function(){return E[p]=!1,b(M)!=M||b(E)==E||b(M,"i")!="/a/i"}))){for(var L=function(A,N){var F,B=this instanceof L,W=n(A),H=N===void 0;return!B&&W&&A.constructor===L&&H?A:(k?W&&!H&&(A=A.source):A instanceof L&&(H&&(N=a.call(A)),A=A.source),O&&(F=!!N&&-1I;)(function(A){A in L||g(L,A,{configurable:!0,get:function(){return b[A]},set:function(N){b[A]=N}})})(C[I++]);(j.constructor=L).prototype=j,d(u,"RegExp",L)}c("RegExp")},{"../internals/descriptors":43,"../internals/fails":51,"../internals/global":60,"../internals/inherit-if-required":68,"../internals/internal-state":71,"../internals/is-forced":74,"../internals/is-regexp":77,"../internals/object-define-property":93,"../internals/object-get-own-property-names":96,"../internals/redefine":110,"../internals/regexp-flags":113,"../internals/regexp-sticky-helpers":114,"../internals/set-species":118,"../internals/well-known-symbol":150}],195:[function(u,x,v){var s=u("../internals/export"),u=u("../internals/regexp-exec");s({target:"RegExp",proto:!0,forced:/./.exec!==u},{exec:u})},{"../internals/export":50,"../internals/regexp-exec":112}],196:[function(f,x,v){var s=f("../internals/redefine"),u=f("../internals/an-object"),n=f("../internals/fails"),o=f("../internals/regexp-flags"),f="toString",g=RegExp.prototype,m=g[f],n=n(function(){return m.call({source:"a",flags:"b"})!="/a/b"}),a=m.name!=f;(n||a)&&s(RegExp.prototype,f,function(){var l=u(this),d=String(l.source),y=l.flags;return"/"+d+"/"+String(y===void 0&&l instanceof RegExp&&!("flags"in g)?o.call(l):y)},{unsafe:!0})},{"../internals/an-object":10,"../internals/fails":51,"../internals/redefine":110,"../internals/regexp-flags":113}],197:[function(u,x,v){var s=u("../internals/collection"),u=u("../internals/collection-strong");x.exports=s("Set",function(o){return function(){return o(this,arguments.length?arguments[0]:void 0)}},u)},{"../internals/collection":32,"../internals/collection-strong":30}],198:[function(m,x,v){var s=m("../internals/export"),u=m("../internals/object-get-own-property-descriptor").f,o=m("../internals/to-length"),f=m("../internals/not-a-regexp"),g=m("../internals/require-object-coercible"),l=m("../internals/correct-is-regexp-logic"),m=m("../internals/is-pure"),n="".endsWith,a=Math.min,l=l("endsWith");s({target:"String",proto:!0,forced:!!(m||l||!(s=u(String.prototype,"endsWith"))||s.writable)&&!l},{endsWith:function(d){var y=String(g(this)),h=(f(d),1=a.length?{value:void 0,done:!0}:(a=s(a,l),n.index+=a.length,{value:a,done:!1})})},{"../internals/define-iterator":41,"../internals/internal-state":71,"../internals/string-multibyte":125}],201:[function(t,x,v){var s=t("../internals/fix-regexp-well-known-symbol-logic"),u=t("../internals/an-object"),o=t("../internals/to-length"),f=t("../internals/require-object-coercible"),g=t("../internals/advance-string-index"),m=t("../internals/regexp-exec-abstract");s("match",1,function(n,a,l){return[function(d){var y=f(this),h=d==null?void 0:d[n];return h!==void 0?h.call(d,y):new RegExp(d)[n](String(y))},function(d){var y=l(a,d,this);if(y.done)return y.value;var h=u(d),c=String(this);if(!h.global)return m(h,c);for(var p=h.unicode,b=[],j=h.lastIndex=0;(M=m(h,c))!==null;){var M=String(M[0]);(b[j]=M)===""&&(h.lastIndex=g(c,o(h.lastIndex),p)),j++}return j===0?null:b}]})},{"../internals/advance-string-index":8,"../internals/an-object":10,"../internals/fix-regexp-well-known-symbol-logic":52,"../internals/regexp-exec-abstract":111,"../internals/require-object-coercible":115,"../internals/to-length":138}],202:[function(t,x,v){var s=t("../internals/export"),u=t("../internals/string-pad").start;s({target:"String",proto:!0,forced:t("../internals/string-pad-webkit-bug")},{padStart:function(o){return u(this,o,1]*>)/g,c=/\$([$&'`]|\d\d?)/g;s("replace",2,function(p,b,j,M){var E=M.REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE,k=M.REPLACE_KEEPS_$0,O=E?"$":"$0";return[function(L,C){var I=m(this),A=L==null?void 0:L[p];return A!==void 0?A.call(L,I,C):b.call(String(I),L,C)},function(L,C){if(!E&&k||typeof C=="string"&&C.indexOf(O)===-1){var I=j(b,L,this,C);if(I.done)return I.value}for(var A,N=u(L),F=String(this),B=typeof C=="function",W=(B||(C=String(C)),N.global),H=(W&&(A=N.unicode,N.lastIndex=0),[]);(T=a(N,F))!==null&&(H.push(T),W);)String(T[0])===""&&(N.lastIndex=n(F,f(N.lastIndex),A));for(var V,K="",J=0,le=0;le>>0;if(C==0)return[];if(k===void 0)return[L];if(!u(k))return j.call(L,k,C);for(var I,A,N,F=[],O=(k.ignoreCase?"i":"")+(k.multiline?"m":"")+(k.unicode?"u":"")+(k.sticky?"y":""),B=0,W=new RegExp(k.source,O+"g");(I=l.call(W,L))&&!(B<(A=W.lastIndex)&&(F.push(L.slice(B,I.index)),1=C));)W.lastIndex===I.index&&W.lastIndex++;return B===L.length?!N&&W.test("")||F.push(""):F.push(L.slice(B)),F.length>C?F.slice(0,C):F}:"0".split(void 0,0).length?function(k,O){return k===void 0&&O===0?[]:j.call(this,k,O)}:j;return[function(k,O){var L=f(this),C=k==null?void 0:k[b];return C!==void 0?C.call(k,L,O):E.call(String(L),k,O)},function(I,O){var L=M(E,I,this,O,E!==j);if(L.done)return L.value;var L=o(I),C=String(this),I=g(L,RegExp),A=L.unicode,N=(L.ignoreCase?"i":"")+(L.multiline?"m":"")+(L.unicode?"u":"")+(p?"y":"g"),F=new I(p?L:"^(?:"+L.source+")",N),B=O===void 0?c:O>>>0;if(B==0)return[];if(C.length===0)return a(F,C)===null?[C]:[];for(var W=0,H=0,V=[];Hne.key){he.splice(ue,0,ne);break}ue===z&&he.push(ne)}ie.updateURL()},forEach:function(ne){for(var ue,ie=V(this).entries,he=j(ne,16))return;for(Bt=0;tr();){if(er=null,Bt>0)if(tr()=="."&&Bt<4)$e++;else return;if(!G.test(tr()))return;for(;G.test(tr());){if(on=parseInt(tr(),10),er===null)er=on;else{if(er==0)return;er=er*10+on}if(er>255)return;$e++}gt[Xe]=gt[Xe]*256+er,Bt++,(Bt==2||Bt==4)&&Xe++}if(Bt!=4)return;break}else if(tr()==":"){if($e++,!tr())return}else if(tr())return;gt[Xe++]=Ht}if(pt!==null)for(Er=Xe-pt,Xe=7;Xe!=0&&Er>0;)sn=gt[Xe],gt[Xe--]=gt[pt+Er-1],gt[pt+--Er]=sn;else if(Xe!=8)return;return gt}(ze.slice(1,-1)))?void(_e.host=Ze):J;if(be(_e))return ze=k(ze),ue.test(ze)||(Ze=function(Be){var gt=Be.split("."),Xe,pt,$e,Ht,Yt,Bt,er;if(gt.length&>[gt.length-1]==""&>.pop(),(Xe=gt.length)>4)return Be;for(pt=[],$e=0;$e1&&Ht.charAt(0)=="0"&&(Yt=q.test(Ht)?16:8,Ht=Ht.slice(Yt==8?1:2)),Ht==="")Bt=0;else{if(!(Yt==10?ee:Yt==8?Z:ne).test(Ht))return Be;Bt=parseInt(Ht,Yt)}pt.push(Bt)}for($e=0;$e=H(256,5-Xe))return null}else if(Bt>255)return null;for(er=pt.pop(),$e=0;$e":1,"`":1}),de=j({},me,{"#":1,"?":1,"{":1,"}":1}),ye=j({},de,{"/":1,":":1,";":1,"=":1,"@":1,"[":1,"\\":1,"]":1,"^":1,"|":1}),ve=function(_e,ze){var Ze=E(_e,0);return 32"u"&&s!==void 0&&{}.toString.call(s)==="[object process]",p=typeof Uint8ClampedArray<"u"&&typeof importScripts<"u"&&typeof MessageChannel<"u";function b(){var z=setTimeout;return function(){return z(M,1)}}var j=new Array(1e3);function M(){for(var z=0;zL,applyPalette:()=>function(B,W,H="rgb565"){if(!B||!B.buffer)throw new Error("quantize() expected RGBA Uint8Array data");if(!(B instanceof Uint8Array||B instanceof Uint8ClampedArray))throw new Error("quantize() expected RGBA Uint8Array data");if(256>24&255,G=Z>>16&255,q=Z>>8&255,Z=255&Z,ee=d(Z,q,G,D),ee=ee in T?T[ee]:T[ee]=function(z,te,ce,me,de){let ye=0,ve=1e100;for(let Re=0;Reve||(ke=be[0],(Ne+=E(ke-z))>ve||(ke=be[1],(Ne+=E(ke-te))>ve||(ke=be[2],(Ne+=E(ke-ce))>ve||(ve=Ne,ye=Re))))}return ye}(Z,q,G,D,W);le[$]=ee}else{const $=H==="rgb444"?y:l;for(let z=0;z>16&255,ue=ie>>8&255,ie=255&ie,he=$(ie,ue,ne),he=he in T?T[he]:T[he]=function(te,ce,me,de){let ye=0,ve=1e100;for(let Re=0;Reve||(ke=be[1],(Ne+=E(ke-ce))>ve||(ke=be[2],(Ne+=E(ke-me))>ve||(ve=Ne,ye=Re)))}return ye}(ie,ue,ne,W);le[z]=he}}return le},default:()=>F,nearestColor:()=>function(B,W,H=j){return B[k(B,W,H)]},nearestColorIndex:()=>k,nearestColorIndexWithDistance:()=>O,prequantize:()=>function(B,{roundRGB:W=5,roundAlpha:H=10,oneBitAlpha:V=null}={}){const K=new Uint32Array(B.buffer);for(let G=0;G>24&255;var J,le=D>>16&255,T=D>>8&255,D=255&D;q=M(q,H),V&&(J=typeof V=="number"?V:127,q=q<=J?0:255),D=M(D,W),T=M(T,W),le=M(le,W),K[G]=q<<24|le<<16|T<<8|D<<0}},quantize:()=>function(B,W,H={}){var{format:V="rgb565",clearAlpha:K=!0,clearAlphaColor:J=0,clearAlphaThreshold:le=0,oneBitAlpha:T=!1}=H;if(!B||!B.buffer)throw new Error("quantize() expected RGBA Uint8Array data");if(!(B instanceof Uint8Array||B instanceof Uint8ClampedArray))throw new Error("quantize() expected RGBA Uint8Array data");B=new Uint32Array(B.buffer);let D=H.useSqrt!==!1;const G=V==="rgba4444",q=function(Ie,Fe){const Ge=Fe==="rgb444"?4096:65536,xe=new Array(Ge),Le=Ie.length;if(Fe==="rgba4444")for(let ot=0;ot>24&255,re=Q>>16&255,se=Q>>8&255,Q=255&Q,ae=d(Q,se,re,Ee);let Ke=ae in xe?xe[ae]:xe[ae]=b();Ke.rc+=Q,Ke.gc+=se,Ke.bc+=re,Ke.ac+=Ee,Ke.cnt++}else if(Fe==="rgb444")for(let ot=0;ot>16&255,Se=Pe>>8&255,Pe=255&Pe,He=y(Pe,Se,we);let Ke=He in xe?xe[He]:xe[He]=b();Ke.rc+=Pe,Ke.gc+=Se,Ke.bc+=we,Ke.cnt++}else for(let ot=0;ot>16&255,qe=Ye>>8&255,Ye=255&Ye,lt=l(Ye,qe,We);let Ke=lt in xe?xe[lt]:xe[lt]=b();Ke.rc+=Ye,Ke.gc+=qe,Ke.bc+=We,Ke.cnt++}return xe}(B,V),Z=q.length,ee=Z-1,ne=new Uint32Array(Z+1);for(var ue=0,ie=0;ie>1,!(q[he=ne[z]].err<=te));$=z)ne[$]=he;ne[$]=ie}var ce,me=ue-W;for(ie=0;ie=ce.mtm&&q[ce.nn].mtm<=ce.tm)break;for(ce.mtm==ee?de=ne[1]=ne[ne[0]--]:(p(q,de),ce.tm=ie),te=q[de].err,$=1;(z=$+$)<=ne[0]&&(zq[ne[z+1]].err&&z++,!(te<=q[he=ne[z]].err));$=z)ne[$]=he;ne[$]=de}var ye=q[ce.nn],ve=ce.cnt,ke=ye.cnt,be=1/(ve+ke);G&&(ce.ac=be*(ve*ce.ac+ke*ye.ac)),ce.rc=be*(ve*ce.rc+ke*ye.rc),ce.gc=be*(ve*ce.gc+ke*ye.gc),ce.bc=be*(ve*ce.bc+ke*ye.bc),ce.cnt+=ye.cnt,ce.mtm=++ie,q[ye.bk].fw=ye.fw,q[ye.fw].bk=ye.bk,ye.mtm=ee}let Ne=[];for(ie=0;;0){let Ie=h(Math.round(q[ie].rc),0,255),Fe=h(Math.round(q[ie].gc),0,255),Ge=h(Math.round(q[ie].bc),0,255),xe=255;G&&(xe=h(Math.round(q[ie].ac),0,255),T&&(Re=typeof T=="number"?T:127,xe=xe<=Re?0:255),K&&xe<=le&&(Ie=Fe=Ge=J,xe=0));var Re=G?[Ie,Fe,Ge,xe]:[Ie,Fe,Ge];if(function(Le,Ee){for(let Q=0;Qfunction(B,W,H=5){if(B.length&&W.length){var V=B.map(D=>D.slice(0,3)),K=H*H,J=B[0].length;for(let D=0;DJ?G.slice(0,3):G.slice();var T=O(V,G.slice(0,3),j),le=T[0],T=T[1];0>>0),J!=0&&(K=Math.max(K,256));const le=H;H=new Uint8Array(K),0>=8,Z-=8;if((te>he||ue)&&(ue?(ie=ne,he=(1<>=8,Z-=8;0>3}function d(B,W,H,V){return B>>4|240&W|(240&H)<<4|(240&V)<<8}function y(B,W,H){return B>>4<<8|240&W|H>>4}function h(B,W,H){return B>8&255)}function A(B,W){for(var H=0;H>1,y=-7,h=o?p-1:0,c=o?-1:1,p=s[u+h];for(h+=c,m=p&(1<<-y)-1,p>>=-y,y+=a;0>=-y,y+=f;0>1,h=g===23?Math.pow(2,-24)-Math.pow(2,-77):0,c=f?0:b-1,p=f?1:-1,b=u<0||u===0&&1/u<0?1:0;for(u=Math.abs(u),isNaN(u)||u===1/0?(a=isNaN(u)?1:0,n=d):(n=Math.floor(Math.log(u)/Math.LN2),u*(f=Math.pow(2,-n))<1&&(n--,f*=2),2<=(u+=1<=n+y?h/f:h*Math.pow(2,1-y))*f&&(n++,f/=2),d<=n+y?(a=0,n=d):1<=n+y?(a=(u*f-1)*Math.pow(2,g),n+=y):(a=u*Math.pow(2,y-1)*Math.pow(2,g),n=0));8<=g;s[o+c]=255&a,c+=p,a/=256,g-=8);for(n=n<Math.abs(re[0])&&(se=1),se=Math.abs(re[2])>Math.abs(re[se])?2:se}function I(re,se){re.f+=se.f,re.b.f+=se.b.f}function A(re,se,Q){return re=re.a,se=se.a,Q=Q.a,se.b.a===re?Q.b.a===re?o(se.a,Q.a)?g(Q.b.a,se.a,Q.a)<=0:0<=g(se.b.a,Q.a,se.a):g(Q.b.a,re,Q.a)<=0:Q.b.a===re?0<=g(se.b.a,re,se.a):(se=f(se.b.a,re,se.a),(re=f(Q.b.a,re,Q.a))<=se)}function N(re){re.a.i=null;var se=re.e;se.a.c=se.c,se.c.a=se.a,re.e=null}function F(re,se){h(re.a),re.c=!1,(re.a=se).i=re}function B(re){for(var se=re.a.a;(re=Ee(re)).a.a===se;);return re.c&&(F(re,se=p(Le(re).a.b,re.a.e)),re=Ee(re)),re}function W(re,se,Q){var ae=new xe;return ae.a=Q,ae.e=ue(re.f,se.e,ae),Q.i=ae}function H(re,se){switch(re.s){case 100130:return(1&se)!=0;case 100131:return se!==0;case 100132:return 0>1]],He[Pe[qe]])?Fe:Ge)(Q,qe),He[Se]=null,We[Se]=Q.b,Q.b=Se}else for(Q.c[-(Se+1)]=null;0Math.max(Pe.a,We.a))){if(o(Se,Pe)){if(0Q.f&&(Q.f*=2,Q.c=Ne(Q.c,Q.f+1)),Q.b===0?we=ae:(we=Q.b,Q.b=Q.c[Q.b]),Q.e[we]=se,Q.c[we]=ae,Q.d[ae]=we,Q.h&&Ge(Q,ae),we):(Q=re.a++,re.c[Q]=se,-(Q+1))}function ke(re){if(re.a===0)return Ie(re.b);var se=re.c[re.d[re.a-1]];if(re.b.a!==0&&o(Re(re.b),se))return Ie(re.b);for(;--re.a,0re.a||o(ae[Pe],ae[We])){we[Q[Se]=Pe]=Se;break}we[Q[Se]=We]=Se,Se=He}}function Ge(re,se){for(var Q=re.d,ae=re.e,we=re.c,Se=se,Pe=Q[Se];;){var He=Se>>1,We=Q[He];if(He==0||o(ae[We],ae[Pe])){we[Q[Se]=Pe]=Se;break}we[Q[Se]=We]=Se,Se=He}}function xe(){this.e=this.a=null,this.f=0,this.c=this.b=this.h=this.d=!1}function Le(re){return re.e.c.b}function Ee(re){return re.e.a.b}(s=he.prototype).x=function(){$(this,0)},s.B=function(re,se){switch(re){case 100142:return;case 100140:switch(se){case 100130:case 100131:case 100132:case 100133:case 100134:return void(this.s=se)}break;case 100141:return void(this.m=!!se);default:return void z(this,100900)}z(this,100901)},s.y=function(re){switch(re){case 100142:return 0;case 100140:return this.s;case 100141:return this.m;default:z(this,100900)}return!1},s.A=function(re,se,Q){this.j[0]=re,this.j[1]=se,this.j[2]=Q},s.z=function(re,se){var Q=se||null;switch(re){case 100100:case 100106:this.h=Q;break;case 100104:case 100110:this.l=Q;break;case 100101:case 100107:this.k=Q;break;case 100102:case 100108:this.i=Q;break;case 100103:case 100109:this.p=Q;break;case 100105:case 100111:this.o=Q;break;case 100112:this.r=Q;break;default:z(this,100900)}},s.C=function(re,se){var Q=!1,ae=[0,0,0];$(this,2);for(var we=0;we<3;++we){var Se=re[we];Se<-1e150&&(Se=-1e150,Q=!0),1e150ae[qe]&&(ae[qe]=Ye,we[qe]=Q)}if(ae[1]-He[1]>ae[Q=0]-He[0]&&(Q=1),He[Q=ae[2]-He[2]>ae[Q]-He[Q]?2:Q]>=ae[Q])Pe[0]=0,Pe[1]=0,Pe[2]=1;else{for(He=We[Q],we=we[Q],We=[ae=0,0,0],He=[He.g[0]-we.g[0],He.g[1]-we.g[1],He.g[2]-we.g[2]],qe=[0,0,0],Q=Se.e;Q!==Se;Q=Q.e)qe[0]=Q.g[0]-we.g[0],qe[1]=Q.g[1]-we.g[1],qe[2]=Q.g[2]-we.g[2],We[0]=He[1]*qe[2]-He[2]*qe[1],We[1]=He[2]*qe[0]-He[0]*qe[2],We[2]=He[0]*qe[1]-He[1]*qe[0],ae<(Ye=We[0]*We[0]+We[1]*We[1]+We[2]*We[2])&&(ae=Ye,Pe[0]=We[0],Pe[1]=We[1],Pe[2]=We[2]);ae<=0&&(Pe[0]=Pe[1]=Pe[2]=0,Pe[C(He)]=1)}Se=!0}for(We=C(Pe),Q=this.b.c,ae=(We+1)%3,we=(We+2)%3,We=0>=1;)++y;if(c=1<>8&255,o[n++]=255&g,o[n++]=g>>8&255,o[n++]=(l!==null?128:0)|y,o[n++]=h,o[n++]=0,l!==null)for(var p=0,b=l.length;p>16&255,o[n++]=j>>8&255,o[n++]=255&j}if(a!==null){if(a<0||65535>8&255,o[n++]=0}var M=!1;this.addFrame=function(E,k,O,L,C,I){if(M===!0&&(--n,M=!1),I=I===void 0?{}:I,E<0||k<0||65535>=1;)++F;var B=1<>8&255,o[n++]=K,o[n++]=0),o[n++]=44,o[n++]=255&E,o[n++]=E>>8&255,o[n++]=255&k,o[n++]=k>>8&255,o[n++]=255&O,o[n++]=O>>8&255,o[n++]=255&L,o[n++]=L>>8&255,o[n++]=A===!0?128|F-1:0,A===!0)for(var J=0,le=N.length;J>16&255,o[n++]=T>>8&255,o[n++]=255&T}return n=function(D,G,q,Z){D[G++]=q;var ee=G++,ne=1<>=8,z-=8,G===ee+256&&(D[ee]=255,ee=G++)}function me(Ie){te|=Ie<>=8,z-=8,G===ee+256&&(D[ee]=255,ee=G++);he===4096?(me(ne),he=1+ie,$=q+1,ye={}):(1<<$<=he&&++$,ye[Ne]=he++),de=be}else de=Re}return me(de),me(ie),ce(1),ee+1===G?D[ee]=0:(D[ee]=G-ee-1,D[G++]=0),G}(o,n,F<2?2:F,C)},this.end=function(){return M===!1&&(o[n++]=59,M=!0),n},this.getOutputBuffer=function(){return o},this.setOutputBuffer=function(E){o=E},this.getOutputBufferPosition=function(){return n},this.setOutputBufferPosition=function(E){n=E}}function u(o,f,g,m){for(var n=o[f++],a=1<>=y,c-=y,k==a)d=1+l,h=(1<<(y=n+1))-1,E=null;else{if(k==l)break;for(var O=k>8,++L;var I=C;if(m>=8;E!==null&&d<4096&&(M[d++]=E<<8|I,h+1<=d&&y<12&&(++y,h=h<<1|1)),E=k}}b!==m&&console.log("Warning, gif stream shorter than expected.")}try{v.GifWriter=s,v.GifReader=function(o){var f=0;if(o[f++]!==71||o[f++]!==73||o[f++]!==70||o[f++]!==56||(o[f++]+1&253)!=56||o[f++]!==97)throw new Error("Invalid GIF 87a/89a header.");var g=o[f++]|o[f++]<<8,m=o[f++]|o[f++]<<8,n=o[f++],a=1<<1+(7&n),l=(o[f++],o[f++],null),d=null,y=(n>>7&&(l=f,f+=3*(d=a)),!0),h=[],c=0,p=null,b=0,j=null;for(this.width=g,this.height=m;y&&f>2&7,f++;break;case 254:for(;;){if(!(0<=(E=o[f++])))throw Error("Invalid block size");if(E===0)break;f+=E}break;default:throw new Error("Unknown graphic control label: 0x"+o[f-1].toString(16))}break;case 44:var E,k=o[f++]|o[f++]<<8,O=o[f++]|o[f++]<<8,L=o[f++]|o[f++]<<8,C=o[f++]|o[f++]<<8,W=o[f++],I=W>>6&1,A=1<<1+(7&W),N=l,F=d,B=!1,W=(W>>7&&(B=!0,N=f,f+=3*(F=A)),f);for(f++;;){if(!(0<=(E=o[f++])))throw Error("Invalid block size");if(E===0)break;f+=E}h.push({x:k,y:O,width:L,height:C,has_local_palette:B,palette_offset:N,palette_size:F,data_offset:W,data_length:f-W,transparent_index:p,interlaced:!!I,delay:c,disposal:b});break;case 59:y=!1;break;default:throw new Error("Unknown gif block: 0x"+o[f-1].toString(16))}this.numFrames=function(){return h.length},this.loopCount=function(){return j},this.frameInfo=function(H){if(H<0||H>=h.length)throw new Error("Frame index out of range.");return h[H]},this.decodeAndBlitFrameBGRA=function(H,V){for(var H=this.frameInfo(H),K=H.width*H.height,J=new Uint8Array(K),le=(u(o,H.data_offset,J,K),H.palette_offset),T=H.transparent_index,D=(T===null&&(T=256),H.width),G=g-D,q=D,Z=4*(H.y*g+H.x),ee=4*((H.y+H.height)*g+H.x),ne=Z,ue=4*G,ie=(H.interlaced===!0&&(ue+=4*g*7),8),he=0,$=J.length;he<$;++he){var z,te,ce=J[he];q===0&&(q=D,ee<=(ne+=ue)&&(ue=4*G+4*g*(ie-1),ne=Z+(D+G)*(ie<<1),ie>>=1)),ce===T?ne+=4:(z=o[le+3*ce],te=o[le+3*ce+1],ce=o[le+3*ce+2],V[ne++]=ce,V[ne++]=te,V[ne++]=z,V[ne++]=255),--q}},this.decodeAndBlitFrameRGBA=function(H,V){for(var H=this.frameInfo(H),K=H.width*H.height,J=new Uint8Array(K),le=(u(o,H.data_offset,J,K),H.palette_offset),T=H.transparent_index,D=(T===null&&(T=256),H.width),G=g-D,q=D,Z=4*(H.y*g+H.x),ee=4*((H.y+H.height)*g+H.x),ne=Z,ue=4*G,ie=(H.interlaced===!0&&(ue+=4*g*7),8),he=0,$=J.length;he<$;++he){var z,te,ce=J[he];q===0&&(q=D,ee<=(ne+=ue)&&(ue=4*G+4*g*(ie-1),ne=Z+(D+G)*(ie<<1),ie>>=1)),ce===T?ne+=4:(z=o[le+3*ce],te=o[le+3*ce+1],ce=o[le+3*ce+2],V[ne++]=z,V[ne++]=te,V[ne++]=ce,V[ne++]=255),--q}}}}catch{}},{}],257:[function(t,x,v){(function(s){var u,o;u=this,o=function(f){function g(U){if(this==null)throw TypeError();var S,P=String(this),R=P.length,U=U?Number(U):0;if(!((U=U!=U?0:U)<0||R<=U))return 55296<=(S=P.charCodeAt(U))&&S<=56319&&U+1>>16-S;return _.tag>>>=S,_.bitcount-=S,R+P}function A(_,S){for(;_.bitcount<24;)_.tag|=_.source[_.sourceIndex++]<<_.bitcount,_.bitcount+=8;for(var P=0,R=0,U=0,X=_.tag;R=2*R+(1&X),X>>>=1,P+=S.table[++U],0<=(R-=S.table[U]););return _.tag=X,_.bitcount-=U,S.trans[P+R]}function N(_,S,P){for(;;){var R=A(_,S);if(R===256)return n;if(R<256)_.dest[_.destLen++]=R;else for(var U,X=I(_,c[R-=257],p[R]),R=A(_,P),Y=U=_.destLen-I(_,b[R],j[R]);Y>>=1,R=U,I(X,2,0)){case 0:P=function(Oe){for(var Je,ut;8this.x2&&(this.x2=_)),typeof S=="number"&&((isNaN(this.y1)||isNaN(this.y2))&&(this.y1=S,this.y2=S),Sthis.y2&&(this.y2=S))},K.prototype.addX=function(_){this.addPoint(_,null)},K.prototype.addY=function(_){this.addPoint(null,_)},K.prototype.addBezier=function(_,S,P,R,U,X,Y,oe){var pe=[_,S],fe=[P,R],je=[U,X],Me=[Y,oe];this.addPoint(_,S),this.addPoint(Y,oe);for(var Te=0;Te<=1;Te++){var ge,Ue=6*pe[Te]-12*fe[Te]+6*je[Te],Ae=-3*pe[Te]+9*fe[Te]-9*je[Te]+3*Me[Te],De=3*fe[Te]-3*pe[Te];Ae==0?Ue==0||0<(ge=-De/Ue)&&ge<1&&(Te===0&&this.addX(V(pe[Te],fe[Te],je[Te],Me[Te],ge)),Te===1&&this.addY(V(pe[Te],fe[Te],je[Te],Me[Te],ge))):(ge=Math.pow(Ue,2)-4*De*Ae)<0||(0<(De=(-Ue+Math.sqrt(ge))/(2*Ae))&&De<1&&(Te===0&&this.addX(V(pe[Te],fe[Te],je[Te],Me[Te],De)),Te===1&&this.addY(V(pe[Te],fe[Te],je[Te],Me[Te],De))),0<(De=(-Ue-Math.sqrt(ge))/(2*Ae))&&De<1&&(Te===0&&this.addX(V(pe[Te],fe[Te],je[Te],Me[Te],De)),Te===1&&this.addY(V(pe[Te],fe[Te],je[Te],Me[Te],De))))}},K.prototype.addQuad=function(_,S,P,R,U,X){P=_+2/3*(P-_),R=S+2/3*(R-S),this.addBezier(_,S,P,R,P+1/3*(U-_),R+1/3*(X-S),U,X)},J.prototype.moveTo=function(_,S){this.commands.push({type:"M",x:_,y:S})},J.prototype.lineTo=function(_,S){this.commands.push({type:"L",x:_,y:S})},J.prototype.curveTo=J.prototype.bezierCurveTo=function(_,S,P,R,U,X){this.commands.push({type:"C",x1:_,y1:S,x2:P,y2:R,x:U,y:X})},J.prototype.quadTo=J.prototype.quadraticCurveTo=function(_,S,P,R){this.commands.push({type:"Q",x1:_,y1:S,x:P,y:R})},J.prototype.close=J.prototype.closePath=function(){this.commands.push({type:"Z"})},J.prototype.extend=function(_){var S;if(_.commands)_=_.commands;else if(_ instanceof K)return S=_,this.moveTo(S.x1,S.y1),this.lineTo(S.x2,S.y1),this.lineTo(S.x2,S.y2),this.lineTo(S.x1,S.y2),void this.close();Array.prototype.push.apply(this.commands,_)},J.prototype.getBoundingBox=function(){for(var _=new K,S=0,P=0,R=0,U=0,X=0;X>8&255,255&_]},Z.USHORT=ee(2),q.SHORT=function(_){return[(_=32768<=_?-(65536-_):_)>>8&255,255&_]},Z.SHORT=ee(2),q.UINT24=function(_){return[_>>16&255,_>>8&255,255&_]},Z.UINT24=ee(3),q.ULONG=function(_){return[_>>24&255,_>>16&255,_>>8&255,255&_]},Z.ULONG=ee(4),q.LONG=function(_){return[(_=2147483648<=_?-(4294967296-_):_)>>24&255,_>>16&255,_>>8&255,255&_]},Z.LONG=ee(4),q.FIXED=q.ULONG,Z.FIXED=Z.ULONG,q.FWORD=q.SHORT,Z.FWORD=Z.SHORT,q.UFWORD=q.USHORT,Z.UFWORD=Z.USHORT,q.LONGDATETIME=function(_){return[0,0,0,0,_>>24&255,_>>16&255,_>>8&255,255&_]},Z.LONGDATETIME=ee(8),q.TAG=function(_){return D.argument(_.length===4,"Tag should be exactly 4 ASCII characters."),[_.charCodeAt(0),_.charCodeAt(1),_.charCodeAt(2),_.charCodeAt(3)]},Z.TAG=ee(4),q.Card8=q.BYTE,Z.Card8=Z.BYTE,q.Card16=q.USHORT,Z.Card16=Z.USHORT,q.OffSize=q.BYTE,Z.OffSize=Z.BYTE,q.SID=q.USHORT,Z.SID=Z.USHORT,q.NUMBER=function(_){return-107<=_&&_<=107?[_+139]:108<=_&&_<=1131?[247+((_-=108)>>8),255&_]:-1131<=_&&_<=-108?[251+((_=-_-108)>>8),255&_]:-32768<=_&&_<=32767?q.NUMBER16(_):q.NUMBER32(_)},Z.NUMBER=function(_){return q.NUMBER(_).length},q.NUMBER16=function(_){return[28,_>>8&255,255&_]},Z.NUMBER16=ee(3),q.NUMBER32=function(_){return[29,_>>24&255,_>>16&255,_>>8&255,255&_]},Z.NUMBER32=ee(5),q.REAL=function(_){for(var S=_.toString(),P=/\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(S),R=(P&&(P=parseFloat("1e"+((P[2]?+P[2]:0)+P[1].length)),S=(Math.round(_*P)/P).toString()),""),U=0,X=S.length;U>8&255,S[S.length]=255&R}return S},Z.UTF16=function(_){return 2*_.length};var ne,ue={"x-mac-croatian":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®Š™´¨≠ŽØ∞±≤≥∆µ∂∑∏š∫ªºΩžø¿¡¬√ƒ≈Ć«Č… ÀÃÕŒœĐ—“”‘’÷◊©⁄€‹›Æ»–·‚„‰ÂćÁčÈÍÎÏÌÓÔđÒÚÛÙıˆ˜¯πË˚¸Êæˇ","x-mac-cyrillic":"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ†°Ґ£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµґЈЄєЇїЉљЊњјЅ¬√ƒ≈∆«»… ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёяабвгдежзийклмнопрстуфхцчшщъыьэю","x-mac-gaelic":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØḂ±≤≥ḃĊċḊḋḞḟĠġṀæøṁṖṗɼƒſṠ«»… ÀÃÕŒœ–—“”‘’ṡẛÿŸṪ€‹›Ŷŷṫ·Ỳỳ⁊ÂÊÁËÈÍÎÏÌÓÔ♣ÒÚÛÙıÝýŴŵẄẅẀẁẂẃ","x-mac-greek":"Ĺ²É³ÖÜ΅àâä΄¨çéèê룙î‰ôö¦€ùûü†ΓΔΘΛΞΠß®©ΣΪ§≠°·Α±≤≥¥ΒΕΖΗΙΚΜΦΫΨΩάΝ¬ΟΡ≈Τ«»… ΥΧΆΈœ–―“”‘’÷ΉΊΌΎέήίόΏύαβψδεφγηιξκλμνοπώρστθωςχυζϊϋΐΰ­","x-mac-icelandic":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûüÝ°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€ÐðÞþý·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ","x-mac-inuit":"ᐃᐄᐅᐆᐊᐋᐱᐲᐳᐴᐸᐹᑉᑎᑏᑐᑑᑕᑖᑦᑭᑮᑯᑰᑲᑳᒃᒋᒌᒍᒎᒐᒑ°ᒡᒥᒦ•¶ᒧ®©™ᒨᒪᒫᒻᓂᓃᓄᓅᓇᓈᓐᓯᓰᓱᓲᓴᓵᔅᓕᓖᓗᓘᓚᓛᓪᔨᔩᔪᔫᔭ… ᔮᔾᕕᕖᕗ–—“”‘’ᕘᕙᕚᕝᕆᕇᕈᕉᕋᕌᕐᕿᖀᖁᖂᖃᖄᖅᖏᖐᖑᖒᖓᖔᖕᙱᙲᙳᙴᙵᙶᖖᖠᖡᖢᖣᖤᖥᖦᕼŁł","x-mac-ce":"ÄĀāÉĄÖÜáąČäčĆć鏟ĎíďĒēĖóėôöõúĚěü†°Ę£§•¶ß®©™ę¨≠ģĮįĪ≤≥īĶ∂∑łĻļĽľĹĺŅņѬ√ńŇ∆«»… ňŐÕőŌ–—“”‘’÷◊ōŔŕŘ‹›řŖŗŠ‚„šŚśÁŤťÍŽžŪÓÔūŮÚůŰűŲųÝýķŻŁżĢˇ",macintosh:"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ","x-mac-romanian":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ĂȘ∞±≤≥¥µ∂∑∏π∫ªºΩăș¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›Țț‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ","x-mac-turkish":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸĞğİıŞş‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙˆ˜¯˘˙˚¸˝˛ˇ"},ie=(G.MACSTRING=function(_,S,P,R){var U=ue[R];if(U!==void 0){for(var X="",Y=0;Y>8&255,Te+256&255)}return fe})(_,R,S);return S},q.INDEX=function(_){for(var S=1,P=[S],R=[],U=0;U<_.length;U+=1){var X=q.OBJECT(_[U]);Array.prototype.push.apply(R,X),S+=X.length,P.push(S)}if(R.length===0)return[0,0];for(var Y=[],oe=1+Math.floor(Math.log(S)/Math.log(2))/8|0,pe=[void 0,q.BYTE,q.USHORT,q.UINT24,q.ULONG][oe],fe=0;fe>8,S[je+1]=255&Me,S=S.concat(R[fe])}return S},Z.TABLE=function(_){for(var S=0,P=_.fields.length,R=0;R>1,oe.skip("uShort",3),De.glyphIndexMap={};for(var ut,et=new Ee.Parser(Ce,Oe+Je+14),tt=new Ee.Parser(Ce,Oe+Je+16+2*ut),ct=new Ee.Parser(Ce,Oe+Je+16+4*ut),Ot=new Ee.Parser(Ce,Oe+Je+16+6*ut),Gt=Oe+Je+16+8*ut,Xt=0;Xt>4,Y=15&Y;if(X==15||(R+=U[X],Y==15))break;R+=U[Y]}return parseFloat(R)}if(32<=S&&S<=246)return S-139;if(247<=S&&S<=250)return 256*(S-247)+_.parseByte()+108;if(251<=S&&S<=254)return 256*-(S-251)-_.parseByte()-108;throw new Error("Invalid b0 "+S)}function cr(_,S,P){var R=new Ee.Parser(_,S=S!==void 0?S:0),U=[],X=[];for(P=P!==void 0?P:_.length;R.relativeOffset>1,ge.length=0,Ae=!0}return function tt(ct){for(var Ot,Gt,Xt,dr,fr,Zr,Tt,Lt,wt,hr,Ft,ar,It=0;ItMath.abs(ar-Oe)?Ce=Ft+ge.shift():Oe=ar+ge.shift(),Te.curveTo(R,U,X,Y,Tt,Lt),Te.curveTo(wt,hr,Ft,ar,Ce,Oe);break;default:console.log("Glyph "+S.index+": unknown operator 1200"+rr),ge.length=0}break;case 14:0>3;break;case 21:2>16),It+=2;break;case 29:fr=ge.pop()+_.gsubrsBias,(Zr=_.gsubrs[fr])&&tt(Zr);break;case 30:for(;0=P.begin&&_=we.length&&(X=R.parseChar(),P.names.push(R.parseString(X)));break;case 2.5:P.numberOfGlyphs=R.parseUShort(),P.offset=new Array(P.numberOfGlyphs);for(var oe=0;oeMe.value.tag?1:-1}),S.fields=S.fields.concat(R),S.fields=S.fields.concat(U),S}function Zl(_,S,P){for(var R=0;R 123 are reserved for internal usage");ge|=1<>>1,X=_[U].tag;if(X===S)return U;X>>1,X=_[U];if(X===S)return U;X>>1,Y=(U=_[X]).start;if(Y===S)return U;Y(U=_[P-1]).end?0:U}function Es(_,S){this.font=_,this.tableName=S}function Ts(_){Es.call(this,_,"gpos")}function an(_){Es.call(this,_,"gsub")}function Jl(_,S,P){for(var R=_.subtables,U=0;US.points.length-1||R.matchedPoints[1]>U.points.length-1)throw Error("Matched points out of range in "+S.name);var Y=S.points[R.matchedPoints[0]],oe=U.points[R.matchedPoints[1]],R={xScale:R.xScale,scale01:R.scale01,scale10:R.scale10,yScale:R.yScale,dx:0,dy:0},oe=Fi([oe],R)[0];R.dx=Y.x-oe.x,R.dy=Y.y-oe.y,X=Fi(U.points,R)}S.points=S.points.concat(X)}}return ru(S.points)}(Ts.prototype=Es.prototype={searchTag:Di,binSearch:Kl,getTable:function(_){var S=this.font.tables[this.tableName];return S=!S&&_?this.font.tables[this.tableName]=this.createDefaultTable():S},getScriptNames:function(){var _=this.getTable();return _?_.scripts.map(function(S){return S.tag}):[]},getDefaultScriptName:function(){var _=this.getTable();if(_){for(var S=!1,P=0;P<_.scripts.length;P++){var R=_.scripts[P].tag;if(R==="DFLT")return R;R==="latn"&&(S=!0)}return S?"latn":void 0}},getScriptTable:function(_,S){var P,R=this.getTable(S);if(R)return P=R.scripts,0<=(R=Di(R.scripts,_=_||"DFLT"))?P[R].script:S?(P.splice(-1-R,0,S={tag:_,script:{defaultLangSys:{reserved:0,reqFeatureIndex:65535,featureIndexes:[]},langSysRecords:[]}}),S.script):void 0},getLangSysTable:function(U,S,P){var R,U=this.getScriptTable(U,P);if(U)return S&&S!=="dflt"&&S!=="DFLT"?0<=(R=Di(U.langSysRecords,S))?U.langSysRecords[R].langSys:P?(U.langSysRecords.splice(-1-R,0,P={tag:S,langSys:{reserved:0,reqFeatureIndex:65535,featureIndexes:[]}}),P.langSys):void 0:U.defaultLangSys},getFeatureTable:function(_,S,P,R){if(_=this.getLangSysTable(_,S,R),_){for(var U,X=_.featureIndexes,Y=this.font.tables[this.tableName].features,oe=0;oe=Y[S-1].tag,"Features must be added in alphabetical order."),Y.push(U={tag:P,feature:{params:0,lookupListIndexes:[]}}),X.push(S),U.feature}},getLookupTables:function(X,S,P,R,U){var X=this.getFeatureTable(X,S,P,U),Y=[];if(X){for(var oe,pe=X.lookupListIndexes,fe=this.font.tables[this.tableName].lookups,je=0;je",X),S.stack.push(Math.round(64*X))}function Ui(_,S){var P=S.stack,R=P.pop(),U=S.fv,X=S.pv,Y=S.ppem,oe=S.deltaBase+16*(_-1),pe=S.deltaShift,fe=S.z0;f.DEBUG&&console.log(S.step,"DELTAP["+_+"]",R,P);for(var je=0;je>4)===Y&&(0<=(Te=(15&Te)-8)&&Te++,f.DEBUG&&console.log(S.step,"DELTAPFIX",Me,"by",Te*pe),Me=fe[Me],U.setRelative(Me,Me,Te*pe,X))}}function Ms(_,S){var P=S.stack,R=P.pop();f.DEBUG&&console.log(S.step,"ROUND[]"),P.push(64*S.round(R/64))}function Bi(_,S){var P=S.stack,R=P.pop(),U=S.ppem,X=S.deltaBase+16*(_-1),Y=S.deltaShift;f.DEBUG&&console.log(S.step,"DELTAC["+_+"]",R,P);for(var oe=0;oe>4)===U&&(0<=(fe=(15&fe)-8)&&fe++,fe=fe*Y,f.DEBUG&&console.log(S.step,"DELTACFIX",pe,"by",fe),S.cvt[pe]+=fe)}}function xu(_,S){var P,U=S.stack,R=U.pop(),U=U.pop(),X=S.z2[R],Y=S.z1[U];f.DEBUG&&console.log(S.step,"SDPVTL["+_+"]",R,U),R=_?(P=X.y-Y.y,Y.x-X.x):(P=Y.x-X.x,Y.y-X.y),S.dpv=Uo(P,R)}function Tn(_,S){var P=S.stack,R=S.prog,U=S.ip;f.DEBUG&&console.log(S.step,"PUSHB["+_+"]");for(var X=0;X<_;X++)P.push(R[++U]);S.ip=U}function kn(_,S){var P=S.ip,R=S.prog,U=S.stack;f.DEBUG&&console.log(S.ip,"PUSHW["+_+"]");for(var X=0;X<_;X++){var Y=R[++P]<<8|R[++P];32768&Y&&(Y=-(1+(65535^Y))),U.push(Y)}S.ip=P}function Qe(_,S,P,R,U,X){var Y,oe,fe=X.stack,pe=_&&fe.pop(),fe=fe.pop(),je=X.rp0,je=X.z0[je],Me=X.z1[fe],Te=X.minDis,ge=X.fv,Ue=X.dpv,Ae=Y=Ue.distance(Me,je,!0,!0),De=0<=Ae?1:-1;Ae=Math.abs(Ae),_&&(oe=X.cvt[pe],R&&Math.abs(Ae-oe)":"_")+(R?"R":"_")+(U===0?"Gr":U===1?"Bl":U===2?"Wh":"")+"]",_?pe+"("+X.cvt[pe]+","+oe+")":"",fe,"(d =",Y,"->",De*Ae,")"),X.rp1=X.rp0,X.rp2=fe,S&&(X.rp0=fe)}ou.prototype.exec=function(_,S){if(typeof S!="number")throw new Error("Point size is not a number!");if(!(2",R),oe.interpolate(Me,X,Y,pe),oe.touch(Me)}_.loop=1},vu.bind(void 0,0),vu.bind(void 0,1),function(_){for(var S=_.stack,P=_.rp0,R=_.z0[P],U=_.loop,X=_.fv,Y=_.pv,oe=_.z1;U--;){var pe=S.pop(),fe=oe[pe];f.DEBUG&&console.log(_.step,(1<_.loop?"loop "+(_.loop-U)+": ":"")+"ALIGNRP[]",pe),X.setRelative(fe,R,0,Y),X.touch(fe)}_.loop=1},function(_){f.DEBUG&&console.log(_.step,"RTDG[]"),_.round=Wh},bu.bind(void 0,0),bu.bind(void 0,1),function(_){var S=_.prog,P=_.ip,R=_.stack,U=S[++P];f.DEBUG&&console.log(_.step,"NPUSHB[]",U);for(var X=0;X"u"?op:sp)(_,function(P,R){if(P)return S(P);var U;try{U=Gi(R)}catch(X){return S(X,null)}return S(null,U)})},f.loadSync=function(_){return Gi(eu(t("fs").readFileSync(_)))},Object.defineProperty(f,"__esModule",{value:!0})},o(typeof v=="object"&&x!==void 0?v:u.opentype={})}).call(this,t("buffer").Buffer)},{buffer:4,fs:2}],258:[function(t,x,v){(function(s){function u(g,m){for(var n=0,a=g.length-1;0<=a;a--){var l=g[a];l==="."?g.splice(a,1):l===".."?(g.splice(a,1),n++):n&&(g.splice(a,1),n--)}if(m)for(;n--;)g.unshift("..");return g}function o(g,m){if(g.filter)return g.filter(m);for(var n=[],a=0;a'.concat(c,"").concat(d,""),this.dummyDOM||(this.dummyDOM=document.getElementById(h).parentNode),this.descriptions?this.descriptions.fallbackElements||(this.descriptions.fallbackElements={}):this.descriptions={fallbackElements:{}},this.descriptions.fallbackElements[l]?this.descriptions.fallbackElements[l].innerHTML!==c&&(this.descriptions.fallbackElements[l].innerHTML=c):this._describeElementHTML("fallback",l,c),y===this.LABEL&&(this.descriptions.labelElements||(this.descriptions.labelElements={}),this.descriptions.labelElements[l]?this.descriptions.labelElements[l].innerHTML!==c&&(this.descriptions.labelElements[l].innerHTML=c):this._describeElementHTML("label",l,c)))},s.default.prototype._describeHTML=function(l,d){var y,h=this.canvas.id;l==="fallback"?(this.dummyDOM.querySelector("#".concat(h+u))?this.dummyDOM.querySelector("#"+h+f).insertAdjacentHTML("beforebegin",'

')):(y='

'),this.dummyDOM.querySelector("#".concat(h,"accessibleOutput"))?this.dummyDOM.querySelector("#".concat(h,"accessibleOutput")).insertAdjacentHTML("beforebegin",y):this.dummyDOM.querySelector("#".concat(h)).innerHTML=y),this.descriptions.fallback=this.dummyDOM.querySelector("#".concat(h).concat(o)),this.descriptions.fallback.innerHTML=d):l==="label"&&(this.dummyDOM.querySelector("#".concat(h+g))?this.dummyDOM.querySelector("#".concat(h+n))&&this.dummyDOM.querySelector("#".concat(h+n)).insertAdjacentHTML("beforebegin",'

')):(y='

'),this.dummyDOM.querySelector("#".concat(h,"accessibleOutputLabel"))?this.dummyDOM.querySelector("#".concat(h,"accessibleOutputLabel")).insertAdjacentHTML("beforebegin",y):this.dummyDOM.querySelector("#"+h).insertAdjacentHTML("afterend",y)),this.descriptions.label=this.dummyDOM.querySelector("#"+h+m),this.descriptions.label.innerHTML=d)},s.default.prototype._describeElementHTML=function(l,d,y){var h,c=this.canvas.id;l==="fallback"?(this.dummyDOM.querySelector("#".concat(c+u))?this.dummyDOM.querySelector("#"+c+f)||this.dummyDOM.querySelector("#"+c+o).insertAdjacentHTML("afterend",'
Canvas elements and their descriptions
')):(h='
Canvas elements and their descriptions
'),this.dummyDOM.querySelector("#".concat(c,"accessibleOutput"))?this.dummyDOM.querySelector("#".concat(c,"accessibleOutput")).insertAdjacentHTML("beforebegin",h):this.dummyDOM.querySelector("#"+c).innerHTML=h),(h=document.createElement("tr")).id=c+"_fte_"+d,this.dummyDOM.querySelector("#"+c+f).appendChild(h),this.descriptions.fallbackElements[d]=this.dummyDOM.querySelector("#".concat(c).concat("_fte_").concat(d)),this.descriptions.fallbackElements[d].innerHTML=y):l==="label"&&(this.dummyDOM.querySelector("#".concat(c+g))?this.dummyDOM.querySelector("#".concat(c+n))||this.dummyDOM.querySelector("#"+c+m).insertAdjacentHTML("afterend",'
')):(h='
'),this.dummyDOM.querySelector("#".concat(c,"accessibleOutputLabel"))?this.dummyDOM.querySelector("#".concat(c,"accessibleOutputLabel")).insertAdjacentHTML("beforebegin",h):this.dummyDOM.querySelector("#"+c).insertAdjacentHTML("afterend",h)),(l=document.createElement("tr")).id=c+"_lte_"+d,this.dummyDOM.querySelector("#"+c+n).appendChild(l),this.descriptions.labelElements[d]=this.dummyDOM.querySelector("#".concat(c).concat("_lte_").concat(d)),this.descriptions.labelElements[d].innerHTML=y)},t=s.default,v.default=t},{"../core/main":283,"core-js/modules/es.array.concat":153,"core-js/modules/es.regexp.exec":195,"core-js/modules/es.string.ends-with":198,"core-js/modules/es.string.replace":204}],264:[function(t,x,v){t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.from"),t("core-js/modules/es.array.map"),t("core-js/modules/es.string.iterator"),t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.from"),t("core-js/modules/es.array.map"),t("core-js/modules/es.string.iterator"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0,t=(t=t("../core/main"))&&t.__esModule?t:{default:t},t.default.prototype._updateGridOutput=function(s){var u,o,f,g;this.dummyDOM.querySelector("#".concat(s,"_summary"))&&(u=this._accessibleOutputs[s],f=function(m,n,a,l){return n="".concat(n," canvas, ").concat(a," by ").concat(l," pixels, contains ").concat(m[0]),n=(m[0]===1?"".concat(n," shape: "):"".concat(n," shapes: ")).concat(m[1]),n}((o=function(m,n){var a,l="",d="",y=0;for(a in n){var h,c=0;for(h in n[a]){var p='
  • ').concat(n[a][h].color," ").concat(a,",");a==="line"?p+=" location = ".concat(n[a][h].pos,", length = ").concat(n[a][h].length," pixels"):(p+=" location = ".concat(n[a][h].pos),a!=="point"&&(p+=", area = ".concat(n[a][h].area," %")),p+="
  • "),l+=p,c++,y++}d=1').concat(n[a][c].color," ").concat(a,"
    "):'').concat(n[a][c].color," ").concat(a," midpoint"),n[a][c].loc.locY";y=y+j+""}return y}(s,this.ingredients.shapes),f!==u.summary.innerHTML&&(u.summary.innerHTML=f),g!==u.map.innerHTML&&(u.map.innerHTML=g),o.details!==u.shapeDetails.innerHTML&&(u.shapeDetails.innerHTML=o.details),this._accessibleOutputs[s]=u)},t=t.default,v.default=t},{"../core/main":283,"core-js/modules/es.array.concat":153,"core-js/modules/es.array.from":162,"core-js/modules/es.array.map":168,"core-js/modules/es.string.iterator":200}],265:[function(t,x,v){t("core-js/modules/es.symbol"),t("core-js/modules/es.symbol.description"),t("core-js/modules/es.symbol.iterator"),t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.fill"),t("core-js/modules/es.array.from"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.map"),t("core-js/modules/es.number.to-fixed"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.regexp.to-string"),t("core-js/modules/es.string.iterator"),t("core-js/modules/web.dom-collections.iterator"),t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.fill"),t("core-js/modules/es.array.map"),t("core-js/modules/es.number.to-fixed"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0;var s=(t=t("../core/main"))&&t.__esModule?t:{default:t};function u(f){return function(g){if(Array.isArray(g)){for(var m=0,n=new Array(g.length);m')):this.dummyDOM.querySelector("#".concat(l)).innerHTML='
    '))):g==="Label"&&(m=l+f+(d=g),this.dummyDOM.querySelector("#".concat(n=l+"accessibleOutput"+g))||(this.dummyDOM.querySelector("#".concat(l,"_Label"))?this.dummyDOM.querySelector("#".concat(l,"_Label")):this.dummyDOM.querySelector("#".concat(l))).insertAdjacentHTML("afterend",'
    '))),this._accessibleOutputs[m]={},f==="textOutput"?(d="#".concat(l,"gridOutput").concat(d),a='
    Text Output

      '),this.dummyDOM.querySelector(d)?this.dummyDOM.querySelector(d).insertAdjacentHTML("beforebegin",a):this.dummyDOM.querySelector("#".concat(n)).innerHTML=a,this._accessibleOutputs[m].list=this.dummyDOM.querySelector("#".concat(m,"_list"))):f==="gridOutput"&&(d="#".concat(l,"textOutput").concat(d),a='
      Grid Output

        '),this.dummyDOM.querySelector(d)?this.dummyDOM.querySelector(d).insertAdjacentHTML("afterend",a):this.dummyDOM.querySelector("#".concat(n)).innerHTML=a,this._accessibleOutputs[m].map=this.dummyDOM.querySelector("#".concat(m,"_map"))),this._accessibleOutputs[m].shapeDetails=this.dummyDOM.querySelector("#".concat(m,"_shapeDetails")),this._accessibleOutputs[m].summary=this.dummyDOM.querySelector("#".concat(m,"_summary"))},s.default.prototype._updateAccsOutput=function(){var f=this.canvas.id;JSON.stringify(this.ingredients.shapes)===this.ingredients.pShapes&&this.ingredients.colors.background===this.ingredients.pBackground||(this.ingredients.pShapes=JSON.stringify(this.ingredients.shapes),this._accessibleOutputs.text&&this._updateTextOutput(f+"textOutput"),this._accessibleOutputs.grid&&this._updateGridOutput(f+"gridOutput"),this._accessibleOutputs.textLabel&&this._updateTextOutput(f+"textOutputLabel"),this._accessibleOutputs.gridLabel&&this._updateGridOutput(f+"gridOutputLabel"))},s.default.prototype._accsBackground=function(f){this.ingredients.pShapes=JSON.stringify(this.ingredients.shapes),this.ingredients.pBackground=this.ingredients.colors.background,this.ingredients.shapes={},this.ingredients.colors.backgroundRGBA!==f&&(this.ingredients.colors.backgroundRGBA=f,this.ingredients.colors.background=this._rgbColorName(f))},s.default.prototype._accsCanvasColors=function(f,g){f==="fill"?this.ingredients.colors.fillRGBA!==g&&(this.ingredients.colors.fillRGBA=g,this.ingredients.colors.fill=this._rgbColorName(g)):f==="stroke"&&this.ingredients.colors.strokeRGBA!==g&&(this.ingredients.colors.strokeRGBA=g,this.ingredients.colors.stroke=this._rgbColorName(g))},s.default.prototype._accsOutput=function(f,g){f==="ellipse"&&g[2]===g[3]?f="circle":f==="rectangle"&&g[2]===g[3]&&(f="square");var m,n,a={},l=!0,d=function(h,c){var p;return h=h==="rectangle"||h==="ellipse"||h==="arc"||h==="circle"||h==="square"?(p=Math.round(c[0]+c[2]/2),Math.round(c[1]+c[3]/2)):h==="triangle"?(p=(c[0]+c[2]+c[4])/3,(c[1]+c[3]+c[5])/3):h==="quadrilateral"?(p=(c[0]+c[2]+c[4]+c[6])/4,(c[1]+c[3]+c[5]+c[7])/4):h==="line"?(p=(c[0]+c[2])/2,(c[1]+c[3])/2):(p=c[0],c[1]),[p,h]}(f,g);if(f==="line"?(a.color=this.ingredients.colors.stroke,a.length=Math.round(this.dist(g[0],g[1],g[2],g[3])),m=this._getPos(g[0],[1]),n=this._getPos(g[2],[3]),a.loc=o(d,this.width,this.height),a.pos=m===n?"at ".concat(m):"from ".concat(m," to ").concat(n)):(f==="point"?a.color=this.ingredients.colors.stroke:(a.color=this.ingredients.colors.fill,a.area=this._getArea(f,g)),a.pos=this._getPos.apply(this,u(d)),a.loc=o(d,this.width,this.height)),this.ingredients.shapes[f]){if(this.ingredients.shapes[f]!==[a]){for(var y in this.ingredients.shapes[f])JSON.stringify(this.ingredients.shapes[f][y])===JSON.stringify(a)&&(l=!1);l===!0&&this.ingredients.shapes[f].push(a)}}else this.ingredients.shapes[f]=[a]},s.default.prototype._getPos=function(n,m){var n=new DOMPointReadOnly(n,m),m=this._renderer.isP3D?new DOMMatrix(this._renderer.uMVMatrix.mat4):this.drawingContext.getTransform(),n=n.matrixTransform(m),m=n.x,n=n.y,a=this.width*this._pixelDensity,l=this.height*this._pixelDensity;return m<.4*a?n<.4*l?"top left":.6*lMath.PI?a+=n:a-=n)):f==="ellipse"||f==="circle"?a=3.14*g[2]/2*g[3]/2:f==="line"||f==="point"?a=0:f==="quadrilateral"?a=Math.abs((g[6]+g[0])*(g[7]-g[1])+(g[0]+g[2])*(g[1]-g[3])+(g[2]+g[4])*(g[3]-g[5])+(g[4]+g[6])*(g[5]-g[7]))/2:f==="rectangle"||f==="square"?a=g[2]*g[3]:f==="triangle"&&(a=Math.abs(g[0]*(g[3]-g[5])+g[2]*(g[5]-g[1])+g[4]*(g[1]-g[3]))/2),this.width*this._pixelDensity),d=this.height*this._pixelDensity,y=[new DOMPoint(0,0),new DOMPoint(l,0),new DOMPoint(l,d),new DOMPoint(0,d)],h=(this._renderer.isP3D?new DOMMatrix(this._renderer.uMVMatrix.mat4):this.drawingContext.getTransform()).inverse(),c=y.map(function(b){return b.matrixTransform(h)}),p=Math.abs((c[3].x+c[0].x)*(c[3].y-c[0].y)+(c[0].x+c[1].x)*(c[0].y-c[1].y)+(c[1].x+c[2].x)*(c[1].y-c[2].y)+(c[2].x+c[3].x)*(c[2].y-c[3].y))/2;return Math.round(100*a/p)},t=s.default,v.default=t},{"../core/main":283,"core-js/modules/es.array.concat":153,"core-js/modules/es.array.fill":156,"core-js/modules/es.array.from":162,"core-js/modules/es.array.iterator":165,"core-js/modules/es.array.map":168,"core-js/modules/es.number.to-fixed":182,"core-js/modules/es.object.to-string":190,"core-js/modules/es.regexp.to-string":196,"core-js/modules/es.string.iterator":200,"core-js/modules/es.symbol":212,"core-js/modules/es.symbol.description":210,"core-js/modules/es.symbol.iterator":211,"core-js/modules/web.dom-collections.iterator":246}],266:[function(t,x,v){t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.concat"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0,t=(t=t("../core/main"))&&t.__esModule?t:{default:t},t.default.prototype._updateTextOutput=function(s){var u,o,f,g;this.dummyDOM.querySelector("#".concat(s,"_summary"))&&(u=this._accessibleOutputs[s],f=function(m,n,a,l){return a="Your output is a, ".concat(a," by ").concat(l," pixels, ").concat(n," canvas containing the following"),a=m===1?"".concat(a," shape:"):"".concat(a," ").concat(m," shapes:"),a}((o=function(m,n){var a,l="",d=0;for(a in n)for(var y in n[a]){var h='
      • ').concat(n[a][y].color," ").concat(a,"");a==="line"?h+=", ".concat(n[a][y].pos,", ").concat(n[a][y].length," pixels long.
      • "):(h+=", at ".concat(n[a][y].pos),a!=="point"&&(h+=", covering ".concat(n[a][y].area,"% of the canvas")),h+="."),l+=h,d++}return{numShapes:d,listShapes:l}}(s,this.ingredients.shapes)).numShapes,this.ingredients.colors.background,this.width,this.height),g=function(m,n){var a,l="",d=0;for(a in n)for(var y in n[a]){var h='').concat(n[a][y].color," ").concat(a,"");a==="line"?h+="location = ".concat(n[a][y].pos,"length = ").concat(n[a][y].length," pixels"):(h+="location = ".concat(n[a][y].pos,""),a!=="point"&&(h+=" area = ".concat(n[a][y].area,"%")),h+=""),l+=h,d++}return l}(s,this.ingredients.shapes),f!==u.summary.innerHTML&&(u.summary.innerHTML=f),o.listShapes!==u.list.innerHTML&&(u.list.innerHTML=o.listShapes),g!==u.shapeDetails.innerHTML&&(u.shapeDetails.innerHTML=g),this._accessibleOutputs[s]=u)},t=t.default,v.default=t},{"../core/main":283,"core-js/modules/es.array.concat":153}],267:[function(t,x,v){var s=(s=t("./core/main"))&&s.__esModule?s:{default:s};t("./core/constants"),t("./core/environment"),t("./core/friendly_errors/stacktrace"),t("./core/friendly_errors/validate_params"),t("./core/friendly_errors/file_errors"),t("./core/friendly_errors/fes_core"),t("./core/friendly_errors/sketch_reader"),t("./core/helpers"),t("./core/legacy"),t("./core/preload"),t("./core/p5.Element"),t("./core/p5.Graphics"),t("./core/p5.Renderer"),t("./core/p5.Renderer2D"),t("./core/rendering"),t("./core/shim"),t("./core/structure"),t("./core/transform"),t("./core/shape/2d_primitives"),t("./core/shape/attributes"),t("./core/shape/curves"),t("./core/shape/vertex"),t("./accessibility/outputs"),t("./accessibility/textOutput"),t("./accessibility/gridOutput"),t("./accessibility/color_namer"),t("./color/color_conversion"),t("./color/creating_reading"),t("./color/p5.Color"),t("./color/setting"),t("./data/p5.TypedDict"),t("./data/local_storage.js"),t("./dom/dom"),t("./accessibility/describe"),t("./events/acceleration"),t("./events/keyboard"),t("./events/mouse"),t("./events/touch"),t("./image/filters"),t("./image/image"),t("./image/loading_displaying"),t("./image/p5.Image"),t("./image/pixels"),t("./io/files"),t("./io/p5.Table"),t("./io/p5.TableRow"),t("./io/p5.XML"),t("./math/calculation"),t("./math/math"),t("./math/noise"),t("./math/p5.Vector"),t("./math/random"),t("./math/trigonometry"),t("./typography/attributes"),t("./typography/loading_displaying"),t("./typography/p5.Font"),t("./utilities/array_functions"),t("./utilities/conversion"),t("./utilities/string_functions"),t("./utilities/time_date"),t("./webgl/3d_primitives"),t("./webgl/interaction"),t("./webgl/light"),t("./webgl/loading"),t("./webgl/material"),t("./webgl/p5.Camera"),t("./webgl/p5.DataArray"),t("./webgl/p5.Geometry"),t("./webgl/p5.Matrix"),t("./webgl/p5.Quat"),t("./webgl/p5.RendererGL.Immediate"),t("./webgl/p5.RendererGL"),t("./webgl/p5.RendererGL.Retained"),t("./webgl/p5.Framebuffer"),t("./webgl/p5.Shader"),t("./webgl/p5.RenderBuffer"),t("./webgl/p5.Texture"),t("./webgl/text"),t("./core/init"),x.exports=s.default},{"./accessibility/color_namer":262,"./accessibility/describe":263,"./accessibility/gridOutput":264,"./accessibility/outputs":265,"./accessibility/textOutput":266,"./color/color_conversion":268,"./color/creating_reading":269,"./color/p5.Color":270,"./color/setting":271,"./core/constants":272,"./core/environment":273,"./core/friendly_errors/fes_core":274,"./core/friendly_errors/file_errors":275,"./core/friendly_errors/sketch_reader":276,"./core/friendly_errors/stacktrace":277,"./core/friendly_errors/validate_params":278,"./core/helpers":279,"./core/init":280,"./core/legacy":282,"./core/main":283,"./core/p5.Element":284,"./core/p5.Graphics":285,"./core/p5.Renderer":286,"./core/p5.Renderer2D":287,"./core/preload":288,"./core/rendering":289,"./core/shape/2d_primitives":290,"./core/shape/attributes":291,"./core/shape/curves":292,"./core/shape/vertex":293,"./core/shim":294,"./core/structure":295,"./core/transform":296,"./data/local_storage.js":297,"./data/p5.TypedDict":298,"./dom/dom":299,"./events/acceleration":300,"./events/keyboard":301,"./events/mouse":302,"./events/touch":303,"./image/filters":304,"./image/image":305,"./image/loading_displaying":306,"./image/p5.Image":307,"./image/pixels":308,"./io/files":309,"./io/p5.Table":310,"./io/p5.TableRow":311,"./io/p5.XML":312,"./math/calculation":313,"./math/math":314,"./math/noise":315,"./math/p5.Vector":316,"./math/random":317,"./math/trigonometry":318,"./typography/attributes":319,"./typography/loading_displaying":320,"./typography/p5.Font":321,"./utilities/array_functions":322,"./utilities/conversion":323,"./utilities/string_functions":324,"./utilities/time_date":325,"./webgl/3d_primitives":326,"./webgl/interaction":328,"./webgl/light":329,"./webgl/loading":330,"./webgl/material":331,"./webgl/p5.Camera":332,"./webgl/p5.DataArray":333,"./webgl/p5.Framebuffer":334,"./webgl/p5.Geometry":335,"./webgl/p5.Matrix":336,"./webgl/p5.Quat":337,"./webgl/p5.RenderBuffer":338,"./webgl/p5.RendererGL":341,"./webgl/p5.RendererGL.Immediate":339,"./webgl/p5.RendererGL.Retained":340,"./webgl/p5.Shader":342,"./webgl/p5.Texture":343,"./webgl/text":344}],268:[function(t,x,v){Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0,t=(t=t("../core/main"))&&t.__esModule?t:{default:t},t.default.ColorConversion={_hsbaToHSLA:function(s){var u=s[0],o=s[1],f=s[2],g=(2-o)*f/2;return g!=0&&(g==1?o=0:g<.5?o/=2-o:o=o*f/(2-2*g)),[u,o,g,s[3]]},_hsbaToRGBA:function(s){var u,o,f,g,m,n=6*s[0],a=s[1],l=s[2];return a===0?[l,l,l,s[3]]:(o=l*(1-a),f=l*(1-a*(n-(u=Math.floor(n)))),a=l*(1-a*(1+u-n)),n=u===1?(g=f,m=l,o):u===2?(g=o,m=l,a):u===3?(g=o,m=f,l):u===4?(g=a,m=o,l):u===5?(g=l,m=o,f):(g=l,m=a,o),[g,m,n,s[3]])},_hslaToHSBA:function(s){var u=s[0],o=s[1],f=s[2],g=f<.5?(1+o)*f:f+o-f*o;return[u,o=2*(g-f)/g,g,s[3]]},_hslaToRGBA:function(s){var u,o=6*s[0],f=s[1],g=s[2];return f===0?[g,g,g,s[3]]:[(u=function(m,n,a){return m<0?m+=6:6<=m&&(m-=6),m<1?n+(a-n)*m:m<3?a:m<4?n+(a-n)*(4-m):n})(2+o,f=2*g-(g=g<.5?(1+f)*g:g+f-g*f),g),u(o,f,g),u(o-2,f,g),s[3]]},_rgbaToHSBA:function(s){var u,o,f=s[0],g=s[1],m=s[2],n=Math.max(f,g,m),a=n-Math.min(f,g,m);return a==0?o=u=0:(o=a/n,f===n?u=(g-m)/a:g===n?u=2+(m-f)/a:m===n&&(u=4+(f-g)/a),u<0?u+=6:6<=u&&(u-=6)),[u/6,o,n,s[3]]},_rgbaToHSLA:function(s){var u,o,f=s[0],g=s[1],m=s[2],n=Math.max(f,g,m),l=Math.min(f,g,m),a=n+l,l=n-l;return l==0?o=u=0:(o=a<1?l/a:l/(2-a),f===n?u=(g-m)/l:g===n?u=2+(m-f)/l:m===n&&(u=4+(f-g)/l),u<0?u+=6:6<=u&&(u-=6)),[u/6,o,a/2,s[3]]}},t=t.default.ColorConversion,v.default=t},{"../core/main":283}],269:[function(t,x,v){function s(n){return(s=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(a){return typeof a}:function(a){return a&&typeof Symbol=="function"&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a})(n)}function u(n){return(u=typeof Symbol=="function"&&s(Symbol.iterator)==="symbol"?function(a){return s(a)}:function(a){return a&&typeof Symbol=="function"&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":s(a)})(n)}t("core-js/modules/es.symbol"),t("core-js/modules/es.symbol.description"),t("core-js/modules/es.symbol.iterator"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.map"),t("core-js/modules/es.object.get-own-property-descriptor"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.string.iterator"),t("core-js/modules/es.weak-map"),t("core-js/modules/web.dom-collections.iterator"),t("core-js/modules/es.array.map"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0;var o=(m=t("../core/main"))&&m.__esModule?m:{default:m},f=function(n){if(n&&n.__esModule)return n;if(n===null||u(n)!=="object"&&typeof n!="function")return{default:n};var a=g();if(a&&a.has(n))return a.get(n);var l,d={},y=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(l in n){var h;Object.prototype.hasOwnProperty.call(n,l)&&((h=y?Object.getOwnPropertyDescriptor(n,l):null)&&(h.get||h.set)?Object.defineProperty(d,l,h):d[l]=n[l])}return d.default=n,a&&a.set(n,d),d}(t("../core/constants"));function g(){var n;return typeof WeakMap!="function"?null:(n=new WeakMap,g=function(){return n},n)}t("./p5.Color"),t("../core/friendly_errors/validate_params"),t("../core/friendly_errors/file_errors"),t("../core/friendly_errors/fes_core"),o.default.prototype.alpha=function(n){return o.default._validateParameters("alpha",arguments),this.color(n)._getAlpha()},o.default.prototype.blue=function(n){return o.default._validateParameters("blue",arguments),this.color(n)._getBlue()},o.default.prototype.brightness=function(n){return o.default._validateParameters("brightness",arguments),this.color(n)._getBrightness()},o.default.prototype.color=function(){for(var n,a=arguments.length,l=new Array(a),d=0;dh[0]?h[0]+=1:y[0]+=1),1<=(d=this.lerp(y[0],h[0],l))&&--d),n=this.lerp(y[1],h[1],l),a=this.lerp(y[2],h[2],l),y=this.lerp(y[3],h[3],l),d*=p[c][0],n*=p[c][1],a*=p[c][2],y*=p[c][3],this.color(d,n,a,y)},o.default.prototype.lightness=function(n){return o.default._validateParameters("lightness",arguments),this.color(n)._getLightness()},o.default.prototype.red=function(n){return o.default._validateParameters("red",arguments),this.color(n)._getRed()},o.default.prototype.saturation=function(n){return o.default._validateParameters("saturation",arguments),this.color(n)._getSaturation()};var m=o.default;v.default=m},{"../core/constants":272,"../core/friendly_errors/fes_core":274,"../core/friendly_errors/file_errors":275,"../core/friendly_errors/validate_params":278,"../core/main":283,"./p5.Color":270,"core-js/modules/es.array.iterator":165,"core-js/modules/es.array.map":168,"core-js/modules/es.object.get-own-property-descriptor":186,"core-js/modules/es.object.to-string":190,"core-js/modules/es.string.iterator":200,"core-js/modules/es.symbol":212,"core-js/modules/es.symbol.description":210,"core-js/modules/es.symbol.iterator":211,"core-js/modules/es.weak-map":244,"core-js/modules/web.dom-collections.iterator":246}],270:[function(d,x,v){function s(b){return(s=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(j){return typeof j}:function(j){return j&&typeof Symbol=="function"&&j.constructor===Symbol&&j!==Symbol.prototype?"symbol":typeof j})(b)}function u(b){return(u=typeof Symbol=="function"&&s(Symbol.iterator)==="symbol"?function(j){return s(j)}:function(j){return j&&typeof Symbol=="function"&&j.constructor===Symbol&&j!==Symbol.prototype?"symbol":s(j)})(b)}d("core-js/modules/es.symbol"),d("core-js/modules/es.symbol.description"),d("core-js/modules/es.symbol.iterator"),d("core-js/modules/es.array.includes"),d("core-js/modules/es.array.iterator"),d("core-js/modules/es.array.join"),d("core-js/modules/es.array.map"),d("core-js/modules/es.array.slice"),d("core-js/modules/es.object.get-own-property-descriptor"),d("core-js/modules/es.object.to-string"),d("core-js/modules/es.regexp.constructor"),d("core-js/modules/es.regexp.exec"),d("core-js/modules/es.regexp.to-string"),d("core-js/modules/es.string.includes"),d("core-js/modules/es.string.iterator"),d("core-js/modules/es.string.trim"),d("core-js/modules/es.weak-map"),d("core-js/modules/web.dom-collections.iterator"),d("core-js/modules/es.array.includes"),d("core-js/modules/es.array.join"),d("core-js/modules/es.array.map"),d("core-js/modules/es.array.slice"),d("core-js/modules/es.object.to-string"),d("core-js/modules/es.regexp.constructor"),d("core-js/modules/es.regexp.exec"),d("core-js/modules/es.regexp.to-string"),d("core-js/modules/es.string.includes"),d("core-js/modules/es.string.trim"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0;var o=n(d("../core/main")),f=function(b){if(b&&b.__esModule)return b;if(b===null||u(b)!=="object"&&typeof b!="function")return{default:b};var j=m();if(j&&j.has(b))return j.get(b);var M,E={},k=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(M in b){var O;Object.prototype.hasOwnProperty.call(b,M)&&((O=k?Object.getOwnPropertyDescriptor(b,M):null)&&(O.get||O.set)?Object.defineProperty(E,M,O):E[M]=b[M])}return E.default=b,j&&j.set(b,E),E}(d("../core/constants")),g=n(d("./color_conversion"));function m(){var b;return typeof WeakMap!="function"?null:(b=new WeakMap,m=function(){return b},b)}function n(b){return b&&b.__esModule?b:{default:b}}function a(b,j){for(var M=0;M"].indexOf(a[0])?void 0:a[0],lineNumber:a[1],columnNumber:a[2],source:m}},this)},parseFFOrSafari:function(g){return g.stack.split(` -`).filter(function(m){return!m.match(f)},this).map(function(m){var n,a;return(m=-1 eval")?m.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,":$1"):m).indexOf("@")===-1&&m.indexOf(":")===-1?{functionName:m}:{functionName:(a=m.match(n=/((.*".+"[^@]*)?[^@]*)(?:@)/))&&a[1]?a[1]:void 0,fileName:(a=this.extractLocation(m.replace(n,"")))[0],lineNumber:a[1],columnNumber:a[2],source:m}},this)},parseOpera:function(g){return!g.stacktrace||-1g.stacktrace.split(` -`).length?this.parseOpera9(g):g.stack?this.parseOpera11(g):this.parseOpera10(g)},parseOpera9:function(g){for(var m=/Line (\d+).*script (?:in )?(\S+)/i,n=g.message.split(` -`),a=[],l=2,d=n.length;l/,"$2").replace(/\([^)]*\)/g,"")||void 0,args:(n=l.match(/\(([^)]*)\)/)?l.replace(/^[^(]+\(([^)]*)\)$/,"$1"):n)===void 0||n==="[arguments not available]"?void 0:n.split(","),fileName:a[0],lineNumber:a[1],columnNumber:a[2],source:m}},this)}}}t.default._getErrorStackParser=function(){return new s},t=t.default,v.default=t},{"../main":283,"core-js/modules/es.array.filter":157,"core-js/modules/es.array.index-of":164,"core-js/modules/es.array.join":166,"core-js/modules/es.array.map":168,"core-js/modules/es.array.slice":169,"core-js/modules/es.regexp.exec":195,"core-js/modules/es.string.match":201,"core-js/modules/es.string.replace":204,"core-js/modules/es.string.split":206}],278:[function(t,x,v){function s(g){return(s=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(m){return typeof m}:function(m){return m&&typeof Symbol=="function"&&m.constructor===Symbol&&m!==Symbol.prototype?"symbol":typeof m})(g)}t("core-js/modules/es.symbol"),t("core-js/modules/es.symbol.description"),t("core-js/modules/es.symbol.iterator"),t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.for-each"),t("core-js/modules/es.array.includes"),t("core-js/modules/es.array.index-of"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.join"),t("core-js/modules/es.array.last-index-of"),t("core-js/modules/es.array.map"),t("core-js/modules/es.array.slice"),t("core-js/modules/es.function.name"),t("core-js/modules/es.map"),t("core-js/modules/es.number.constructor"),t("core-js/modules/es.object.get-own-property-descriptor"),t("core-js/modules/es.object.get-prototype-of"),t("core-js/modules/es.object.keys"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.reflect.construct"),t("core-js/modules/es.regexp.exec"),t("core-js/modules/es.regexp.to-string"),t("core-js/modules/es.set"),t("core-js/modules/es.string.includes"),t("core-js/modules/es.string.iterator"),t("core-js/modules/es.string.split"),t("core-js/modules/es.weak-map"),t("core-js/modules/web.dom-collections.for-each"),t("core-js/modules/web.dom-collections.iterator"),t("core-js/modules/es.symbol"),t("core-js/modules/es.symbol.description"),t("core-js/modules/es.symbol.iterator"),t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.for-each"),t("core-js/modules/es.array.includes"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.join"),t("core-js/modules/es.array.last-index-of"),t("core-js/modules/es.array.map"),t("core-js/modules/es.array.slice"),t("core-js/modules/es.function.name"),t("core-js/modules/es.number.constructor"),t("core-js/modules/es.object.keys"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.regexp.exec"),t("core-js/modules/es.regexp.to-string"),t("core-js/modules/es.set"),t("core-js/modules/es.string.includes"),t("core-js/modules/es.string.iterator"),t("core-js/modules/es.string.split"),t("core-js/modules/web.dom-collections.for-each"),t("core-js/modules/web.dom-collections.iterator"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0;var u=(u=t("../main"))&&u.__esModule?u:{default:u};(function(g){if(!(g&&g.__esModule)&&!(g===null||f(g)!=="object"&&typeof g!="function")){var m=o();if(m&&m.has(g))return m.get(g);var n,a={},l=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(n in g){var d;Object.prototype.hasOwnProperty.call(g,n)&&((d=l?Object.getOwnPropertyDescriptor(g,n):null)&&(d.get||d.set)?Object.defineProperty(a,n,d):a[n]=g[n])}a.default=g,m&&m.set(g,a)}})(t("../constants")),t("../internationalization");function o(){var g;return typeof WeakMap!="function"?null:(g=new WeakMap,o=function(){return g},g)}function f(g){return(f=typeof Symbol=="function"&&s(Symbol.iterator)==="symbol"?function(m){return s(m)}:function(m){return m&&typeof Symbol=="function"&&m.constructor===Symbol&&m!==Symbol.prototype?"symbol":s(m)})(g)}u.default._validateParameters=u.default._clearValidateParamsCache=function(){},t=u.default,v.default=t},{"../../../docs/parameterData.json":void 0,"../constants":272,"../internationalization":281,"../main":283,"core-js/modules/es.array.concat":153,"core-js/modules/es.array.for-each":161,"core-js/modules/es.array.includes":163,"core-js/modules/es.array.index-of":164,"core-js/modules/es.array.iterator":165,"core-js/modules/es.array.join":166,"core-js/modules/es.array.last-index-of":167,"core-js/modules/es.array.map":168,"core-js/modules/es.array.slice":169,"core-js/modules/es.function.name":174,"core-js/modules/es.map":175,"core-js/modules/es.number.constructor":179,"core-js/modules/es.object.get-own-property-descriptor":186,"core-js/modules/es.object.get-prototype-of":188,"core-js/modules/es.object.keys":189,"core-js/modules/es.object.to-string":190,"core-js/modules/es.reflect.construct":192,"core-js/modules/es.regexp.exec":195,"core-js/modules/es.regexp.to-string":196,"core-js/modules/es.set":197,"core-js/modules/es.string.includes":199,"core-js/modules/es.string.iterator":200,"core-js/modules/es.string.split":206,"core-js/modules/es.symbol":212,"core-js/modules/es.symbol.description":210,"core-js/modules/es.symbol.iterator":211,"core-js/modules/es.weak-map":244,"core-js/modules/web.dom-collections.for-each":245,"core-js/modules/web.dom-collections.iterator":246}],279:[function(t,x,v){function s(g){return(s=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(m){return typeof m}:function(m){return m&&typeof Symbol=="function"&&m.constructor===Symbol&&m!==Symbol.prototype?"symbol":typeof m})(g)}function u(g){return(u=typeof Symbol=="function"&&s(Symbol.iterator)==="symbol"?function(m){return s(m)}:function(m){return m&&typeof Symbol=="function"&&m.constructor===Symbol&&m!==Symbol.prototype?"symbol":s(m)})(g)}t("core-js/modules/es.symbol"),t("core-js/modules/es.symbol.description"),t("core-js/modules/es.symbol.iterator"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.object.get-own-property-descriptor"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.string.iterator"),t("core-js/modules/es.weak-map"),t("core-js/modules/web.dom-collections.iterator"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0;var o=function(g){if(g&&g.__esModule)return g;if(g===null||u(g)!=="object"&&typeof g!="function")return{default:g};var m=f();if(m&&m.has(g))return m.get(g);var n,a={},l=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(n in g){var d;Object.prototype.hasOwnProperty.call(g,n)&&((d=l?Object.getOwnPropertyDescriptor(g,n):null)&&(d.get||d.set)?Object.defineProperty(a,n,d):a[n]=g[n])}return a.default=g,m&&m.set(g,a),a}(t("./constants"));function f(){var g;return typeof WeakMap!="function"?null:(g=new WeakMap,f=function(){return g},g)}v.default={modeAdjust:function(g,m,n,a,l){return l===o.CORNER?{x:g,y:m,w:n,h:a}:l===o.CORNERS?{x:g,y:m,w:n-g,h:a-m}:l===o.RADIUS?{x:g-n,y:m-a,w:2*n,h:2*a}:l===o.CENTER?{x:g-.5*n,y:m-.5*a,w:n,h:a}:void 0}}},{"./constants":272,"core-js/modules/es.array.iterator":165,"core-js/modules/es.object.get-own-property-descriptor":186,"core-js/modules/es.object.to-string":190,"core-js/modules/es.string.iterator":200,"core-js/modules/es.symbol":212,"core-js/modules/es.symbol.description":210,"core-js/modules/es.symbol.iterator":211,"core-js/modules/es.weak-map":244,"core-js/modules/web.dom-collections.iterator":246}],280:[function(t,x,v){t("core-js/modules/es.array.iterator"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.promise"),t("core-js/modules/es.string.iterator"),t("core-js/modules/web.dom-collections.iterator"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.promise"),t("core-js/modules/es.string.iterator"),t("core-js/modules/web.dom-collections.iterator");var s=(u=t("../core/main"))&&u.__esModule?u:{default:u};t("./internationalization");var u=Promise.resolve();Promise.all([new Promise(function(o,f){document.readyState==="complete"?o():window.addEventListener("load",o,!1)}),u]).then(function(){window._setupDone!==void 0?console.warn("p5.js seems to have been imported multiple times. Please remove the duplicate import"):window.mocha||(window.setup&&typeof window.setup=="function"||window.draw&&typeof window.draw=="function")&&!s.default.instance&&new s.default})},{"../core/main":283,"./internationalization":281,"core-js/modules/es.array.iterator":165,"core-js/modules/es.object.to-string":190,"core-js/modules/es.promise":191,"core-js/modules/es.string.iterator":200,"core-js/modules/web.dom-collections.iterator":246}],281:[function(t,x,v){t("core-js/modules/es.array.includes"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.join"),t("core-js/modules/es.array.slice"),t("core-js/modules/es.object.keys"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.promise"),t("core-js/modules/es.regexp.exec"),t("core-js/modules/es.string.includes"),t("core-js/modules/es.string.iterator"),t("core-js/modules/es.string.split"),t("core-js/modules/web.dom-collections.iterator"),t("core-js/modules/es.array.includes"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.join"),t("core-js/modules/es.array.slice"),t("core-js/modules/es.object.keys"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.promise"),t("core-js/modules/es.regexp.exec"),t("core-js/modules/es.string.includes"),t("core-js/modules/es.string.iterator"),t("core-js/modules/es.string.split"),t("core-js/modules/web.dom-collections.iterator"),Object.defineProperty(v,"__esModule",{value:!0}),v.setTranslatorLanguage=v.currentTranslatorLanguage=v.availableTranslatorLanguages=v.initialize=v.translator=void 0;var s,u,o=g(t("i18next")),f=g(t("i18next-browser-languagedetector"));function g(a){return a&&a.__esModule?a:{default:a}}function m(a,l){for(var d=0;d=I.width||E>=I.height?[0,0,0,0]:this._getPixel(M,E);return L=new u.default.Image(k*C,O*C),L.pixelDensity(C),L.canvas.getContext("2d").drawImage(I,M,E,k*C,O*C,0,0,k*C,O*C),L}},{key:"textLeading",value:function(M){return typeof M=="number"?(this._setProperty("_leadingSet",!0),this._setProperty("_textLeading",M),this._pInst):this._textLeading}},{key:"textStyle",value:function(M){return M?(M!==o.NORMAL&&M!==o.ITALIC&&M!==o.BOLD&&M!==o.BOLDITALIC||this._setProperty("_textStyle",M),this._applyTextProperties()):this._textStyle}},{key:"textAscent",value:function(){return this._textAscent===null&&this._updateTextMetrics(),this._textAscent}},{key:"textDescent",value:function(){return this._textDescent===null&&this._updateTextMetrics(),this._textDescent}},{key:"textAlign",value:function(M,E){return M!==void 0?(this._setProperty("_textAlign",M),E!==void 0&&this._setProperty("_textBaseline",E),this._applyTextProperties()):{horizontal:this._textAlign,vertical:this._textBaseline}}},{key:"textWrap",value:function(M){return this._setProperty("_textWrap",M),this._textWrap}},{key:"text",value:function(M,E,k,O,L){var C,I,A,N,F=this._pInst,B=this._textWrap,W=Number.MAX_VALUE,H=k;if((this._doFill||this._doStroke)&&M!==void 0){if(C=(M=(M=typeof M!="string"?M.toString():M).replace(/(\t)/g," ")).split(` -`),O!==void 0){switch(this._rectMode===o.CENTER&&(E-=O/2),this._textAlign){case o.CENTER:E+=O/2;break;case o.RIGHT:E+=O}if(L!==void 0){this._rectMode===o.CENTER&&(k-=L/2,H-=L/2);var M=k,V=F.textAscent();switch(this._textBaseline){case o.BOTTOM:N=k+L,k=Math.max(N,k),H+=V;break;case o.CENTER:N=k+L/2,k=Math.max(N,k),H+=V/2}W=k+L-V,this._textBaseline===o.CENTER&&(W=M+L-V/2)}else this._textBaseline!==o.BOTTOM&&this._textBaseline!==o.CENTER||(H=k-(M=F.textSize()*this._textLeading)/2,W=k+M/2);if(B===o.WORD){for(var K=[],J=0;Jf.HALF_PI&&l<=3*f.HALF_PI?Math.atan(y/h*Math.tan(l))+f.PI:Math.atan(y/h*Math.tan(l))+f.TWO_PI,d=d<=f.HALF_PI?Math.atan(y/h*Math.tan(d)):d>f.HALF_PI&&d<=3*f.HALF_PI?Math.atan(y/h*Math.tan(d))+f.PI:Math.atan(y/h*Math.tan(d))+f.TWO_PI),da||Math.abs(this.accelerationY-this.pAccelerationY)>a||Math.abs(this.accelerationZ-this.pAccelerationZ)>a)&&j.deviceMoved(),typeof j.deviceTurned=="function"&&(h=this._toDegrees(this.rotationX)+180,c=this._toDegrees(this.pRotationX)+180,y=u+180,0>>16,m[1+a]=(65280&n[l])>>>8,m[2+a]=255&n[l],m[3+a]=(4278190080&n[l])>>>24},_toImageData:function(m){return m instanceof ImageData?m:m.getContext("2d").getImageData(0,0,m.width,m.height)},_createImageData:function(m,n){return g._tmpCanvas=document.createElement("canvas"),g._tmpCtx=g._tmpCanvas.getContext("2d"),this._tmpCtx.createImageData(m,n)},apply:function(m,y,a){var l=m.getContext("2d"),d=l.getImageData(0,0,m.width,m.height),y=y(d,a);y instanceof ImageData?l.putImageData(y,0,0,0,0,m.width,m.height):l.putImageData(d,0,0,0,0,m.width,m.height)},threshold:function(m){for(var n=1>8)/l,a[d+1]=255*(h*n>>8)/l,a[d+2]=255*(c*n>>8)/l}},dilate:function(m){for(var n,a,l,d,y,h,c,p,b,j=g._toPixels(m),M=0,E=j.length?j.length/4:0,k=new Int32Array(E);M>16&255)+151*(d>>8&255)+28*(255&d))<(c=77*(b>>16&255)+151*(b>>8&255)+28*(255&b))&&(l=b,d=c),d<(c=77*((b=g._getARGB(j,p))>>16&255)+151*(b>>8&255)+28*(255&b))&&(l=b,d=c),d<(p=77*(y>>16&255)+151*(y>>8&255)+28*(255&y))&&(l=y,d=p),d<(b=77*(h>>16&255)+151*(h>>8&255)+28*(255&h))&&(l=h,d=b),k[M++]=l;g._setPixels(j,k)},erode:function(m){for(var n,a,l,d,y,h,c,p,b,j=g._toPixels(m),M=0,E=j.length?j.length/4:0,k=new Int32Array(E);M>16&255)+151*(b>>8&255)+28*(255&b))<(d=77*(d>>16&255)+151*(d>>8&255)+28*(255&d))&&(l=b,d=c),(c=77*((b=g._getARGB(j,p))>>16&255)+151*(b>>8&255)+28*(255&b))>16&255)+151*(y>>8&255)+28*(255&y))>16&255)+151*(h>>8&255)+28*(255&h))>>24],l+=B[(16711680&he)>>16],d+=B[(65280&he)>>8],y+=B[255&he],a+=o[F],c++}J[p=G+A]=h/a,le[p]=l/a,T[p]=d/a,D[p]=y/a}G+=k}for(j=(b=-s)*k,N=G=0;N"+H.length.toString()+" out of "+N.toString()),z.next=48,new Promise(function(te){return setTimeout(te,0)});z.next=50;break;case 48:z.next=39;break;case 50:L||V.html("Frames processed, generating color palette..."),this.loop(),this.pixelDensity(W),le=(0,n.GIFEncoder)(),T=function(te){for(var ce=new Uint8Array(te.length*te[0].length),me=0;me"+ee.toString()+" out of "+N.toString()),z.next=68,new Promise(function(te){return setTimeout(te,0)});case 68:ee++,z.next=60;break;case 71:le.finish(),he=le.bytesView(),he=new Blob([he],{type:"image/gif"}),H=[],this._recording=!1,this.loop(),L||(V.html("Done. Downloading your gif!🌸"),0=l&&(l=Math.floor(d.timeDisplayed/l),d.timeDisplayed=0,d.lastChangeTime=y,d.displayIndex+=l,d.loopCount=Math.floor(d.displayIndex/d.numFrames),d.loopLimit!==null&&d.loopCount>=d.loopLimit?d.playing=!1:(y=d.displayIndex%d.numFrames,this.drawingContext.putImageData(d.frames[y].image,0,0),d.displayIndex=y,this.setModified(!0))))}},{key:"_setProperty",value:function(a,l){this[a]=l,this.setModified(!0)}},{key:"loadPixels",value:function(){s.default.Renderer2D.prototype.loadPixels.call(this),this.setModified(!0)}},{key:"updatePixels",value:function(a,l,d,y){s.default.Renderer2D.prototype.updatePixels.call(this,a,l,d,y),this.setModified(!0)}},{key:"get",value:function(a,l,d,y){return s.default._validateParameters("p5.Image.get",arguments),s.default.Renderer2D.prototype.get.apply(this,arguments)}},{key:"_getPixel",value:function(){for(var a=arguments.length,l=new Array(a),d=0;d/g,">").replace(/"/g,""").replace(/'/g,"'")}function a(l,d){d&&d!==!0&&d!=="true"||(d="");var y="";return(l=l||"untitled")&&l.includes(".")&&(y=l.split(".").pop()),d&&y!==d&&(y=d,l="".concat(l,".").concat(y)),[l,y]}t("../core/friendly_errors/validate_params"),t("../core/friendly_errors/file_errors"),t("../core/friendly_errors/fes_core"),u.default.prototype.loadJSON=function(){for(var l=arguments.length,d=new Array(l),y=0;y"),c.print(""),c.print(' '),c.print(""),c.print(""),c.print(" "),p[0]!=="0"){c.print(" ");for(var k=0;k".concat(O)),c.print(" ")}c.print(" ")}for(var L=0;L");for(var C=0;C".concat(I)),c.print(" ")}c.print(" ")}c.print("
        "),c.print(""),c.print("")}c.close(),c.clear()},u.default.prototype.writeFile=function(c,d,y){var h="application/octet-stream",c=(u.default.prototype._isSafari()&&(h="text/plain"),new Blob(c,{type:h}));u.default.prototype.downloadFile(c,d,y)},u.default.prototype.downloadFile=function(l,c,p){var h,c=a(c,p),p=c[0];l instanceof Blob?f.default.saveAs(l,p):((h=document.createElement("a")).href=l,h.download=p,h.onclick=function(b){document.body.removeChild(b.target),b.stopPropagation()},h.style.display="none",document.body.appendChild(h),u.default.prototype._isSafari()&&(l=(l=`Hello, Safari user! To download this file... -1. Go to File --> Save As. -2. Choose "Page Source" as the Format. -`)+'3. Name it with this extension: ."'.concat(c[1],'"'),alert(l)),h.click())},u.default.prototype._checkFileExtension=a,u.default.prototype._isSafari=function(){return window.HTMLElement.toString().includes("Constructor")},t=u.default,v.default=t},{"../core/friendly_errors/fes_core":274,"../core/friendly_errors/file_errors":275,"../core/friendly_errors/validate_params":278,"../core/main":283,"core-js/modules/es.array.concat":153,"core-js/modules/es.array.includes":163,"core-js/modules/es.array.iterator":165,"core-js/modules/es.array.last-index-of":167,"core-js/modules/es.array.map":168,"core-js/modules/es.array.slice":169,"core-js/modules/es.array.splice":171,"core-js/modules/es.function.name":174,"core-js/modules/es.object.from-entries":185,"core-js/modules/es.object.to-string":190,"core-js/modules/es.promise":191,"core-js/modules/es.regexp.exec":195,"core-js/modules/es.regexp.to-string":196,"core-js/modules/es.string.includes":199,"core-js/modules/es.string.iterator":200,"core-js/modules/es.string.replace":204,"core-js/modules/es.string.split":206,"core-js/modules/es.symbol":212,"core-js/modules/es.symbol.description":210,"core-js/modules/es.symbol.iterator":211,"core-js/modules/es.typed-array.copy-within":213,"core-js/modules/es.typed-array.every":214,"core-js/modules/es.typed-array.fill":215,"core-js/modules/es.typed-array.filter":216,"core-js/modules/es.typed-array.find":218,"core-js/modules/es.typed-array.find-index":217,"core-js/modules/es.typed-array.for-each":221,"core-js/modules/es.typed-array.includes":222,"core-js/modules/es.typed-array.index-of":223,"core-js/modules/es.typed-array.iterator":226,"core-js/modules/es.typed-array.join":227,"core-js/modules/es.typed-array.last-index-of":228,"core-js/modules/es.typed-array.map":229,"core-js/modules/es.typed-array.reduce":231,"core-js/modules/es.typed-array.reduce-right":230,"core-js/modules/es.typed-array.reverse":232,"core-js/modules/es.typed-array.set":233,"core-js/modules/es.typed-array.slice":234,"core-js/modules/es.typed-array.some":235,"core-js/modules/es.typed-array.sort":236,"core-js/modules/es.typed-array.subarray":237,"core-js/modules/es.typed-array.to-locale-string":238,"core-js/modules/es.typed-array.to-string":239,"core-js/modules/es.typed-array.uint8-array":242,"core-js/modules/web.dom-collections.iterator":246,"core-js/modules/web.url":248,"es6-promise/auto":249,"fetch-jsonp":251,"file-saver":252,"whatwg-fetch":261}],310:[function(t,x,v){t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.index-of"),t("core-js/modules/es.array.join"),t("core-js/modules/es.array.splice"),t("core-js/modules/es.regexp.constructor"),t("core-js/modules/es.regexp.exec"),t("core-js/modules/es.regexp.to-string"),t("core-js/modules/es.string.match"),t("core-js/modules/es.string.replace"),t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.index-of"),t("core-js/modules/es.array.join"),t("core-js/modules/es.array.splice"),t("core-js/modules/es.regexp.constructor"),t("core-js/modules/es.regexp.exec"),t("core-js/modules/es.regexp.to-string"),t("core-js/modules/es.string.match"),t("core-js/modules/es.string.replace"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0;var s=(t=t("../core/main"))&&t.__esModule?t:{default:t};function u(o,f){for(var g=0;g>>0},getSeed:function(){return a},rand:function(){return(l=(1664525*l+1013904223)%d)/d}};y.setSeed(n),u=new Array(4096);for(var h=0;h<4096;h++)u[h]=y.rand()},m.default);v.default=m},{"../core/main":283}],316:[function(t,x,v){function s(a){return(s=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(l){return typeof l}:function(l){return l&&typeof Symbol=="function"&&l.constructor===Symbol&&l!==Symbol.prototype?"symbol":typeof l})(a)}function u(a){return(u=typeof Symbol=="function"&&s(Symbol.iterator)==="symbol"?function(l){return s(l)}:function(l){return l&&typeof Symbol=="function"&&l.constructor===Symbol&&l!==Symbol.prototype?"symbol":s(l)})(a)}t("core-js/modules/es.symbol"),t("core-js/modules/es.symbol.description"),t("core-js/modules/es.symbol.iterator"),t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.every"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.some"),t("core-js/modules/es.math.sign"),t("core-js/modules/es.number.constructor"),t("core-js/modules/es.number.epsilon"),t("core-js/modules/es.number.is-finite"),t("core-js/modules/es.object.get-own-property-descriptor"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.string.iterator"),t("core-js/modules/es.string.sub"),t("core-js/modules/es.weak-map"),t("core-js/modules/web.dom-collections.iterator"),t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.every"),t("core-js/modules/es.array.some"),t("core-js/modules/es.math.sign"),t("core-js/modules/es.number.constructor"),t("core-js/modules/es.number.epsilon"),t("core-js/modules/es.number.is-finite"),t("core-js/modules/es.string.sub"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0;var o=(n=t("../core/main"))&&n.__esModule?n:{default:n},f=function(a){if(a&&a.__esModule)return a;if(a===null||u(a)!=="object"&&typeof a!="function")return{default:a};var l=g();if(l&&l.has(a))return l.get(a);var d,y={},h=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(d in a){var c;Object.prototype.hasOwnProperty.call(a,d)&&((c=h?Object.getOwnPropertyDescriptor(a,d):null)&&(c.get||c.set)?Object.defineProperty(y,d,c):y[d]=a[d])}return y.default=a,l&&l.set(a,y),y}(t("../core/constants"));function g(){var a;return typeof WeakMap!="function"?null:(a=new WeakMap,g=function(){return a},a)}function m(a,l){for(var d=0;d>>0},s.default.prototype.randomSeed=function(m){this._lcgSetSeed(u,m),this._gaussian_previous=!1},s.default.prototype.random=function(m,n){var a,l;return s.default._validateParameters("random",arguments),a=this[u]!=null?this._lcg(u):Math.random(),m===void 0?a:n===void 0?Array.isArray(m)?m[Math.floor(a*m.length)]:a*m:(nG&&(ue=V,ee=F,ne=B,V=$+G*(Z&&$=o?f.substring(f.length-o,f.length):f}},s.default.prototype.unhex=function(u){return u instanceof Array?u.map(s.default.prototype.unhex):parseInt("0x".concat(u),16)},t=s.default,v.default=t},{"../core/main":283,"core-js/modules/es.array.map":168,"core-js/modules/es.number.constructor":179,"core-js/modules/es.object.to-string":190,"core-js/modules/es.regexp.to-string":196,"core-js/modules/es.string.repeat":203}],324:[function(t,x,v){t("core-js/modules/es.symbol"),t("core-js/modules/es.symbol.description"),t("core-js/modules/es.symbol.iterator"),t("core-js/modules/es.array.filter"),t("core-js/modules/es.array.index-of"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.join"),t("core-js/modules/es.array.map"),t("core-js/modules/es.array.slice"),t("core-js/modules/es.number.to-fixed"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.regexp.constructor"),t("core-js/modules/es.regexp.exec"),t("core-js/modules/es.regexp.to-string"),t("core-js/modules/es.string.iterator"),t("core-js/modules/es.string.match"),t("core-js/modules/es.string.pad-start"),t("core-js/modules/es.string.replace"),t("core-js/modules/es.string.split"),t("core-js/modules/es.string.trim"),t("core-js/modules/web.dom-collections.iterator"),t("core-js/modules/es.array.filter"),t("core-js/modules/es.array.index-of"),t("core-js/modules/es.array.join"),t("core-js/modules/es.array.map"),t("core-js/modules/es.array.slice"),t("core-js/modules/es.number.to-fixed"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.regexp.constructor"),t("core-js/modules/es.regexp.exec"),t("core-js/modules/es.regexp.to-string"),t("core-js/modules/es.string.match"),t("core-js/modules/es.string.pad-start"),t("core-js/modules/es.string.replace"),t("core-js/modules/es.string.split"),t("core-js/modules/es.string.trim"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0;var s=(n=t("../core/main"))&&n.__esModule?n:{default:n};function u(a,l){return function(d){if(Array.isArray(d))return d}(a)||function(d,y){if(Symbol.iterator in Object(d)||Object.prototype.toString.call(d)==="[object Arguments]"){var h=[],c=!0,p=!1,b=void 0;try{for(var j,M=d[Symbol.iterator]();!(c=(j=M.next()).done)&&(h.push(j.value),!y||h.length!==y);c=!0);}catch(E){p=!0,b=E}finally{try{c||M.return==null||M.return()}finally{if(p)throw b}}return h}}(a,l)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function o(a,l,d){var h=u(a.toString().split("."),2),y=h[0],h=h[1];return d===void 0?(y=y.padStart(l,"0"),h?y+"."+h:y):(y=(a=u(a.toFixed(d).toString().split("."),2))[0],h=a[1],y=y.padStart(l,"0"),h===void 0?y:y+"."+h)}function f(h,l){var d=(h=h.toString()).indexOf("."),y=d!==-1?h.substring(d):"",h=(h=d!==-1?h.substring(0,d):h).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",");if(l===0)y="";else if(l!==void 0)if(l>y.length)for(var c=l-(y+=d===-1?".":"").length+1,p=0;p=f.TWO_PI?"".concat(E="ellipse","|"):"".concat(E="arc","|").concat(c,"|").concat(p,"|").concat(b,"|")).concat(j,"|"),E=(this.geometryInHash(M)||((a=new o.default.Geometry(j,1,function(){if(c.toFixed(10)!==p.toFixed(10)){b!==f.PIE&&b!==void 0||(this.vertices.push(new o.default.Vector(.5,.5,0)),this.uvs.push([.5,.5]));for(var k=0;k<=j;k++){var L=(p-c)*(k/j)+c,O=.5+Math.cos(L)/2,L=.5+Math.sin(L)/2;this.vertices.push(new o.default.Vector(O,L,0)),this.uvs.push([O,L]),k>5&31)/31,(q>>10&31)/31)),new u.default.Vector(ee,ne,ue)),he=1;he<=3;he++){var $=Z+12*he,$=new u.default.Vector(J.getFloat32($,!0),J.getFloat32(4+$,!0),J.getFloat32(8+$,!0));I.vertices.push($),I.vertexNormals.push(ie),T&&W.push(N,F,B)}I.faces.push([3*G,3*G+1,3*G+2]),I.uvs.push([0,0],[0,0],[0,0])}})(L,C);else{if(C=new DataView(C),!("TextDecoder"in window))return console.warn("Sorry, ASCII STL loading only works in browsers that support TextDecoder (https://caniuse.com/#feat=textencoder)");C=new TextDecoder("utf-8").decode(C).split(` -`),function(I,A){for(var N,F,B="",W=[],H=0;Hthis.cameraFar&&(l=this.cameraFar),Math.acos(Math.max(-1,Math.min(1,s.default.Vector.dot(d,y))))+b),b=m;(p<=0||p>=Math.PI)&&(this.upX*=-1,this.upY*=-1,this.upZ*=-1),y.mult(Math.cos(p)),c.mult(Math.cos(b)*Math.sin(p)),h.mult(Math.sin(b)*Math.sin(p)),d.set(y).add(c).add(h),this.eyeX=l*d.x+this.centerX,this.eyeY=l*d.y+this.centerY,this.eyeZ=l*d.z+this.centerZ,this.camera(this.eyeX,this.eyeY,this.eyeZ,this.centerX,this.centerY,this.centerZ,this.upX,this.upY,this.upZ)}},{key:"_orbitFree",value:function(p,b,M){var d=this.eyeX-this.centerX,y=this.eyeY-this.centerY,h=this.eyeZ-this.centerZ,l=Math.hypot(d,y,h),d=new s.default.Vector(d,y,h).normalize(),y=new s.default.Vector(this.upX,this.upY,this.upZ),h=s.default.Vector.cross(y,d).normalize(),c=s.default.Vector.cross(d,h),E=Math.atan2(b,p),E=(c.mult(Math.sin(E)),h.mult(Math.cos(E)).add(c),Math.sqrt(p*p+b*b)),c=s.default.Vector.cross(d,h),p=((l=(l*=Math.pow(10,M))this.cameraFar&&(l=this.cameraFar),Math.cos(E)),b=Math.sin(E),M=y.dot(d),E=y.dot(h),j=M*p+E*b,M=-M*b+E*p,E=y.dot(c);y.x=j*d.x+M*h.x+E*c.x,y.y=j*d.y+M*h.y+E*c.y,y.z=j*d.z+M*h.z+E*c.z,h.mult(-b),d.mult(p).add(h).mult(l),this.camera(d.x+this.centerX,d.y+this.centerY,d.z+this.centerZ,this.centerX,this.centerY,this.centerZ,y.x,y.y,y.z)}},{key:"_isActive",value:function(){return this===this._renderer._curCamera}}])&&u(f.prototype,g),o}(),s.default.prototype.setCamera=function(o){this._renderer._curCamera=o,this._renderer.uPMatrix.set(o.projMatrix),this._renderer.uViewMatrix.set(o.cameraMatrix)},t=s.default.Camera,v.default=t},{"../core/main":283,"core-js/modules/es.array.slice":169,"core-js/modules/es.math.hypot":176,"core-js/modules/es.string.sub":208}],333:[function(t,x,v){t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.slice"),t("core-js/modules/es.math.log2"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.typed-array.float32-array"),t("core-js/modules/es.typed-array.copy-within"),t("core-js/modules/es.typed-array.every"),t("core-js/modules/es.typed-array.fill"),t("core-js/modules/es.typed-array.filter"),t("core-js/modules/es.typed-array.find"),t("core-js/modules/es.typed-array.find-index"),t("core-js/modules/es.typed-array.for-each"),t("core-js/modules/es.typed-array.includes"),t("core-js/modules/es.typed-array.index-of"),t("core-js/modules/es.typed-array.iterator"),t("core-js/modules/es.typed-array.join"),t("core-js/modules/es.typed-array.last-index-of"),t("core-js/modules/es.typed-array.map"),t("core-js/modules/es.typed-array.reduce"),t("core-js/modules/es.typed-array.reduce-right"),t("core-js/modules/es.typed-array.reverse"),t("core-js/modules/es.typed-array.set"),t("core-js/modules/es.typed-array.slice"),t("core-js/modules/es.typed-array.some"),t("core-js/modules/es.typed-array.sort"),t("core-js/modules/es.typed-array.subarray"),t("core-js/modules/es.typed-array.to-locale-string"),t("core-js/modules/es.typed-array.to-string"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.slice"),t("core-js/modules/es.math.log2"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.typed-array.float32-array"),t("core-js/modules/es.typed-array.copy-within"),t("core-js/modules/es.typed-array.every"),t("core-js/modules/es.typed-array.fill"),t("core-js/modules/es.typed-array.filter"),t("core-js/modules/es.typed-array.find"),t("core-js/modules/es.typed-array.find-index"),t("core-js/modules/es.typed-array.for-each"),t("core-js/modules/es.typed-array.includes"),t("core-js/modules/es.typed-array.index-of"),t("core-js/modules/es.typed-array.iterator"),t("core-js/modules/es.typed-array.join"),t("core-js/modules/es.typed-array.last-index-of"),t("core-js/modules/es.typed-array.map"),t("core-js/modules/es.typed-array.reduce"),t("core-js/modules/es.typed-array.reduce-right"),t("core-js/modules/es.typed-array.reverse"),t("core-js/modules/es.typed-array.set"),t("core-js/modules/es.typed-array.slice"),t("core-js/modules/es.typed-array.some"),t("core-js/modules/es.typed-array.sort"),t("core-js/modules/es.typed-array.subarray"),t("core-js/modules/es.typed-array.to-locale-string"),t("core-js/modules/es.typed-array.to-string"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0,t=(t=t("../core/main"))&&t.__esModule?t:{default:t};function s(u,o){for(var f=0;f=this.width||I>=this.height)&&(console.warn("The x and y values passed to p5.Framebuffer.get are outside of its range and will be clamped."),C=this.target.constrain(C,0,this.width-1),I=this.target.constrain(I,0,this.height-1)),(0,m.readPixelWebGL)(this.gl,this.framebuffer,C*this.density,I*this.density,F.format,F.type);C=this.target.constrain(C,0,this.width-1),I=this.target.constrain(I,0,this.height-1),A=this.target.constrain(A,1,this.width-C),N=this.target.constrain(N,1,this.height-I);for(var B=(0,m.readPixelsWebGL)(void 0,this.gl,this.framebuffer,C*this.density,I*this.density,A*this.density,N*this.density,F.format,F.type),W=new Uint8ClampedArray(A*N*this.density*this.density*4),H=(W.fill(255),F.type===this.gl.RGB?3:4),V=0;Vthis.vertices.length-1-this.detailX;j--)c.add(this.vertexNormals[j]);c=o.default.Vector.div(c,this.detailX);for(var M=this.vertices.length-1;M>this.vertices.length-1-this.detailX;M--)this.vertexNormals[M]=c;return this}},{key:"_makeTriangleEdges",value:function(){for(var c=this.edges.length=0;c 65535 triangles. Your web browser does not support the WebGL Extension OES_element_index_uint.");d.drawElements(d.TRIANGLES,l.vertexCount,l.indexBufferType,0)}else d.drawArrays(n||d.TRIANGLES,0,l.vertexCount)},o.default.RendererGL.prototype._drawPoints=function(n,a){var l=this.GL,d=this._getImmediatePointShader();this._setPointUniforms(d),this._bindBuffer(a,l.ARRAY_BUFFER,this._vToNArray(n),Float32Array,l.STATIC_DRAW),d.enableAttrib(d.attributes.aPosition,3),this._applyColorBlend(this.curStrokeColor),l.drawArrays(l.Points,0,n.length),d.unbindShader()};var m=o.default.RendererGL;v.default=m},{"../core/constants":272,"../core/main":283,"./p5.RenderBuffer":338,"./p5.RendererGL":341,"core-js/modules/es.array.fill":156,"core-js/modules/es.array.iterator":165,"core-js/modules/es.array.some":170,"core-js/modules/es.object.get-own-property-descriptor":186,"core-js/modules/es.object.keys":189,"core-js/modules/es.object.to-string":190,"core-js/modules/es.string.iterator":200,"core-js/modules/es.symbol":212,"core-js/modules/es.symbol.description":210,"core-js/modules/es.symbol.iterator":211,"core-js/modules/es.typed-array.copy-within":213,"core-js/modules/es.typed-array.every":214,"core-js/modules/es.typed-array.fill":215,"core-js/modules/es.typed-array.filter":216,"core-js/modules/es.typed-array.find":218,"core-js/modules/es.typed-array.find-index":217,"core-js/modules/es.typed-array.float32-array":219,"core-js/modules/es.typed-array.for-each":221,"core-js/modules/es.typed-array.includes":222,"core-js/modules/es.typed-array.index-of":223,"core-js/modules/es.typed-array.iterator":226,"core-js/modules/es.typed-array.join":227,"core-js/modules/es.typed-array.last-index-of":228,"core-js/modules/es.typed-array.map":229,"core-js/modules/es.typed-array.reduce":231,"core-js/modules/es.typed-array.reduce-right":230,"core-js/modules/es.typed-array.reverse":232,"core-js/modules/es.typed-array.set":233,"core-js/modules/es.typed-array.slice":234,"core-js/modules/es.typed-array.some":235,"core-js/modules/es.typed-array.sort":236,"core-js/modules/es.typed-array.subarray":237,"core-js/modules/es.typed-array.to-locale-string":238,"core-js/modules/es.typed-array.to-string":239,"core-js/modules/es.typed-array.uint16-array":240,"core-js/modules/es.typed-array.uint32-array":241,"core-js/modules/es.weak-map":244,"core-js/modules/web.dom-collections.iterator":246}],341:[function(A,x,v){function s(V){return(s=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(K){return typeof K}:function(K){return K&&typeof Symbol=="function"&&K.constructor===Symbol&&K!==Symbol.prototype?"symbol":typeof K})(V)}function u(V){return(u=typeof Symbol=="function"&&s(Symbol.iterator)==="symbol"?function(K){return s(K)}:function(K){return K&&typeof Symbol=="function"&&K.constructor===Symbol&&K!==Symbol.prototype?"symbol":s(K)})(V)}A("core-js/modules/es.symbol"),A("core-js/modules/es.symbol.description"),A("core-js/modules/es.symbol.iterator"),A("core-js/modules/es.array.concat"),A("core-js/modules/es.array.copy-within"),A("core-js/modules/es.array.every"),A("core-js/modules/es.array.fill"),A("core-js/modules/es.array.flat"),A("core-js/modules/es.array.flat-map"),A("core-js/modules/es.array.from"),A("core-js/modules/es.array.includes"),A("core-js/modules/es.array.iterator"),A("core-js/modules/es.array.map"),A("core-js/modules/es.array.slice"),A("core-js/modules/es.array.some"),A("core-js/modules/es.array.unscopables.flat"),A("core-js/modules/es.array.unscopables.flat-map"),A("core-js/modules/es.map"),A("core-js/modules/es.object.assign"),A("core-js/modules/es.object.get-own-property-descriptor"),A("core-js/modules/es.object.get-prototype-of"),A("core-js/modules/es.object.to-string"),A("core-js/modules/es.reflect.construct"),A("core-js/modules/es.reflect.get"),A("core-js/modules/es.regexp.to-string"),A("core-js/modules/es.set"),A("core-js/modules/es.string.includes"),A("core-js/modules/es.string.iterator"),A("core-js/modules/es.typed-array.float32-array"),A("core-js/modules/es.typed-array.float64-array"),A("core-js/modules/es.typed-array.int16-array"),A("core-js/modules/es.typed-array.uint8-array"),A("core-js/modules/es.typed-array.uint16-array"),A("core-js/modules/es.typed-array.uint32-array"),A("core-js/modules/es.typed-array.copy-within"),A("core-js/modules/es.typed-array.every"),A("core-js/modules/es.typed-array.fill"),A("core-js/modules/es.typed-array.filter"),A("core-js/modules/es.typed-array.find"),A("core-js/modules/es.typed-array.find-index"),A("core-js/modules/es.typed-array.for-each"),A("core-js/modules/es.typed-array.includes"),A("core-js/modules/es.typed-array.index-of"),A("core-js/modules/es.typed-array.iterator"),A("core-js/modules/es.typed-array.join"),A("core-js/modules/es.typed-array.last-index-of"),A("core-js/modules/es.typed-array.map"),A("core-js/modules/es.typed-array.reduce"),A("core-js/modules/es.typed-array.reduce-right"),A("core-js/modules/es.typed-array.reverse"),A("core-js/modules/es.typed-array.set"),A("core-js/modules/es.typed-array.slice"),A("core-js/modules/es.typed-array.some"),A("core-js/modules/es.typed-array.sort"),A("core-js/modules/es.typed-array.subarray"),A("core-js/modules/es.typed-array.to-locale-string"),A("core-js/modules/es.typed-array.to-string"),A("core-js/modules/es.weak-map"),A("core-js/modules/web.dom-collections.iterator"),A("core-js/modules/es.symbol"),A("core-js/modules/es.symbol.description"),A("core-js/modules/es.symbol.iterator"),A("core-js/modules/es.array.concat"),A("core-js/modules/es.array.copy-within"),A("core-js/modules/es.array.every"),A("core-js/modules/es.array.fill"),A("core-js/modules/es.array.flat"),A("core-js/modules/es.array.flat-map"),A("core-js/modules/es.array.from"),A("core-js/modules/es.array.includes"),A("core-js/modules/es.array.iterator"),A("core-js/modules/es.array.map"),A("core-js/modules/es.array.slice"),A("core-js/modules/es.array.some"),A("core-js/modules/es.array.unscopables.flat"),A("core-js/modules/es.array.unscopables.flat-map"),A("core-js/modules/es.map"),A("core-js/modules/es.object.assign"),A("core-js/modules/es.object.to-string"),A("core-js/modules/es.set"),A("core-js/modules/es.string.includes"),A("core-js/modules/es.string.iterator"),A("core-js/modules/es.typed-array.float32-array"),A("core-js/modules/es.typed-array.float64-array"),A("core-js/modules/es.typed-array.int16-array"),A("core-js/modules/es.typed-array.uint8-array"),A("core-js/modules/es.typed-array.uint16-array"),A("core-js/modules/es.typed-array.uint32-array"),A("core-js/modules/es.typed-array.copy-within"),A("core-js/modules/es.typed-array.every"),A("core-js/modules/es.typed-array.fill"),A("core-js/modules/es.typed-array.filter"),A("core-js/modules/es.typed-array.find"),A("core-js/modules/es.typed-array.find-index"),A("core-js/modules/es.typed-array.for-each"),A("core-js/modules/es.typed-array.includes"),A("core-js/modules/es.typed-array.index-of"),A("core-js/modules/es.typed-array.iterator"),A("core-js/modules/es.typed-array.join"),A("core-js/modules/es.typed-array.last-index-of"),A("core-js/modules/es.typed-array.map"),A("core-js/modules/es.typed-array.reduce"),A("core-js/modules/es.typed-array.reduce-right"),A("core-js/modules/es.typed-array.reverse"),A("core-js/modules/es.typed-array.set"),A("core-js/modules/es.typed-array.slice"),A("core-js/modules/es.typed-array.some"),A("core-js/modules/es.typed-array.sort"),A("core-js/modules/es.typed-array.subarray"),A("core-js/modules/es.typed-array.to-locale-string"),A("core-js/modules/es.typed-array.to-string"),A("core-js/modules/web.dom-collections.iterator"),Object.defineProperty(v,"__esModule",{value:!0}),v.readPixelsWebGL=W,v.readPixelWebGL=H,v.default=void 0;var o=l(A("../core/main")),f=function(V){if(V&&V.__esModule)return V;if(V===null||u(V)!=="object"&&typeof V!="function")return{default:V};var K=a();if(K&&K.has(V))return K.get(V);var J,le={},T=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(J in V){var D;Object.prototype.hasOwnProperty.call(V,J)&&((D=T?Object.getOwnPropertyDescriptor(V,J):null)&&(D.get||D.set)?Object.defineProperty(le,J,D):le[J]=V[J])}return le.default=V,K&&K.set(V,le),le}(A("../core/constants")),g=l(A("./GeometryBuilder")),m=l(A("libtess")),n=(A("./p5.Shader"),A("./p5.Camera"),A("../core/p5.Renderer"),A("./p5.Matrix"),A("./p5.Framebuffer"),A("path"),A("./p5.Texture"));function a(){var V;return typeof WeakMap!="function"?null:(V=new WeakMap,a=function(){return V},V)}function l(V){return V&&V.__esModule?V:{default:V}}function d(V){return function(K){if(Array.isArray(K)){for(var J=0,le=new Array(K.length);J vTexCoord.y; - bool y1 = p1.y > vTexCoord.y; - bool y2 = p2.y > vTexCoord.y; - - // could web be under the curve (after t1)? - if (y1 ? !y2 : y0) { - // add the coverage for t1 - coverage.x += saturate(C1.x + 0.5); - // calculate the anti-aliasing for t1 - weight.x = min(weight.x, abs(C1.x)); - } - - // are we outside the curve (after t2)? - if (y1 ? !y0 : y2) { - // subtract the coverage for t2 - coverage.x -= saturate(C2.x + 0.5); - // calculate the anti-aliasing for t2 - weight.x = min(weight.x, abs(C2.x)); - } -} - -// this is essentially the same as coverageX, but with the axes swapped -void coverageY(vec2 p0, vec2 p1, vec2 p2) { - - vec2 C1, C2; - calulateCrossings(p0, p1, p2, C1, C2); - - bool x0 = p0.x > vTexCoord.x; - bool x1 = p1.x > vTexCoord.x; - bool x2 = p2.x > vTexCoord.x; - - if (x1 ? !x2 : x0) { - coverage.y -= saturate(C1.y + 0.5); - weight.y = min(weight.y, abs(C1.y)); - } - - if (x1 ? !x0 : x2) { - coverage.y += saturate(C2.y + 0.5); - weight.y = min(weight.y, abs(C2.y)); - } -} - -void main() { - - // calculate the pixel scale based on screen-coordinates - pixelScale = hardness / fwidth(vTexCoord); - - // which grid cell is this pixel in? - ivec2 gridCoord = ifloor(vTexCoord * vec2(uGridSize)); - - // intersect curves in this row - { - // the index into the row info bitmap - int rowIndex = gridCoord.y + uGridOffset.y; - // fetch the info texel - vec4 rowInfo = getTexel(uSamplerRows, rowIndex, uGridImageSize); - // unpack the rowInfo - int rowStrokeIndex = getInt16(rowInfo.xy); - int rowStrokeCount = getInt16(rowInfo.zw); - - for (int iRowStroke = INT(0); iRowStroke < N; iRowStroke++) { - if (iRowStroke >= rowStrokeCount) - break; - - // each stroke is made up of 3 points: the start and control point - // and the start of the next curve. - // fetch the indices of this pair of strokes: - vec4 strokeIndices = getTexel(uSamplerRowStrokes, rowStrokeIndex++, uCellsImageSize); - - // unpack the stroke index - int strokePos = getInt16(strokeIndices.xy); - - // fetch the two strokes - vec4 stroke0 = getTexel(uSamplerStrokes, strokePos + INT(0), uStrokeImageSize); - vec4 stroke1 = getTexel(uSamplerStrokes, strokePos + INT(1), uStrokeImageSize); - - // calculate the coverage - coverageX(stroke0.xy, stroke0.zw, stroke1.xy); - } - } - - // intersect curves in this column - { - int colIndex = gridCoord.x + uGridOffset.x; - vec4 colInfo = getTexel(uSamplerCols, colIndex, uGridImageSize); - int colStrokeIndex = getInt16(colInfo.xy); - int colStrokeCount = getInt16(colInfo.zw); - - for (int iColStroke = INT(0); iColStroke < N; iColStroke++) { - if (iColStroke >= colStrokeCount) - break; - - vec4 strokeIndices = getTexel(uSamplerColStrokes, colStrokeIndex++, uCellsImageSize); - - int strokePos = getInt16(strokeIndices.xy); - vec4 stroke0 = getTexel(uSamplerStrokes, strokePos + INT(0), uStrokeImageSize); - vec4 stroke1 = getTexel(uSamplerStrokes, strokePos + INT(1), uStrokeImageSize); - coverageY(stroke0.xy, stroke0.zw, stroke1.xy); - } - } - - weight = saturate(1.0 - weight * 2.0); - float distance = max(weight.x + weight.y, minDistance); // manhattan approx. - float antialias = abs(dot(coverage, weight) / distance); - float cover = min(abs(coverage.x), abs(coverage.y)); - OUT_COLOR = vec4(uMaterialColor.rgb, 1.) * uMaterialColor.a; - OUT_COLOR *= saturate(max(antialias, cover)); -} -`,lineVert:I+`/* - Part of the Processing project - http://processing.org - Copyright (c) 2012-15 The Processing Foundation - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -#define PROCESSING_LINE_SHADER - -precision mediump int; - -uniform mat4 uModelViewMatrix; -uniform mat4 uProjectionMatrix; -uniform float uStrokeWeight; - -uniform bool uUseLineColor; -uniform vec4 uMaterialColor; - -uniform vec4 uViewport; -uniform int uPerspective; -uniform int uStrokeJoin; - -IN vec4 aPosition; -IN vec3 aTangentIn; -IN vec3 aTangentOut; -IN float aSide; -IN vec4 aVertexColor; - -OUT vec4 vColor; -OUT vec2 vTangent; -OUT vec2 vCenter; -OUT vec2 vPosition; -OUT float vMaxDist; -OUT float vCap; -OUT float vJoin; - -vec2 lineIntersection(vec2 aPoint, vec2 aDir, vec2 bPoint, vec2 bDir) { - // Rotate and translate so a starts at the origin and goes out to the right - bPoint -= aPoint; - vec2 rotatedBFrom = vec2( - bPoint.x*aDir.x + bPoint.y*aDir.y, - bPoint.y*aDir.x - bPoint.x*aDir.y - ); - vec2 bTo = bPoint + bDir; - vec2 rotatedBTo = vec2( - bTo.x*aDir.x + bTo.y*aDir.y, - bTo.y*aDir.x - bTo.x*aDir.y - ); - float intersectionDistance = - rotatedBTo.x + (rotatedBFrom.x - rotatedBTo.x) * rotatedBTo.y / - (rotatedBTo.y - rotatedBFrom.y); - return aPoint + aDir * intersectionDistance; -} - -void main() { - // Caps have one of either the in or out tangent set to 0 - vCap = (aTangentIn == vec3(0.)) != (aTangentOut == (vec3(0.))) - ? 1. : 0.; - - // Joins have two unique, defined tangents - vJoin = ( - aTangentIn != vec3(0.) && - aTangentOut != vec3(0.) && - aTangentIn != aTangentOut - ) ? 1. : 0.; - - vec4 posp = uModelViewMatrix * aPosition; - vec4 posqIn = uModelViewMatrix * (aPosition + vec4(aTangentIn, 0)); - vec4 posqOut = uModelViewMatrix * (aPosition + vec4(aTangentOut, 0)); - - float facingCamera = pow( - // The word space tangent's z value is 0 if it's facing the camera - abs(normalize(posqIn-posp).z), - - // Using pow() here to ramp \`facingCamera\` up from 0 to 1 really quickly - // so most lines get scaled and don't get clipped - 0.25 - ); - - // Moving vertices slightly toward the camera - // to avoid depth-fighting with the fill triangles. - // This prevents popping effects due to half of - // the line disappearing behind the geometry faces. - - float zOffset = mix(-0.00045, -1., facingCamera); - posp.z -= zOffset; - posqIn.z -= zOffset; - posqOut.z -= zOffset; - - vec4 p = uProjectionMatrix * posp; - vec4 qIn = uProjectionMatrix * posqIn; - vec4 qOut = uProjectionMatrix * posqOut; - vCenter = p.xy; - - // formula to convert from clip space (range -1..1) to screen space (range 0..[width or height]) - // screen_p = (p.xy/p.w + <1,1>) * 0.5 * uViewport.zw - - // prevent division by W by transforming the tangent formula (div by 0 causes - // the line to disappear, see https://github.com/processing/processing/issues/5183) - // t = screen_q - screen_p - // - // tangent is normalized and we don't care which aDirection it points to (+-) - // t = +- normalize( screen_q - screen_p ) - // t = +- normalize( (q.xy/q.w+<1,1>)*0.5*uViewport.zw - (p.xy/p.w+<1,1>)*0.5*uViewport.zw ) - // - // extract common factor, <1,1> - <1,1> cancels out - // t = +- normalize( (q.xy/q.w - p.xy/p.w) * 0.5 * uViewport.zw ) - // - // convert to common divisor - // t = +- normalize( ((q.xy*p.w - p.xy*q.w) / (p.w*q.w)) * 0.5 * uViewport.zw ) - // - // remove the common scalar divisor/factor, not needed due to normalize and +- - // (keep uViewport - can't remove because it has different components for x and y - // and corrects for aspect ratio, see https://github.com/processing/processing/issues/5181) - // t = +- normalize( (q.xy*p.w - p.xy*q.w) * uViewport.zw ) - - vec2 tangentIn = normalize((qIn.xy*p.w - p.xy*qIn.w) * uViewport.zw); - vec2 tangentOut = normalize((qOut.xy*p.w - p.xy*qOut.w) * uViewport.zw); - - vec2 curPerspScale; - if(uPerspective == 1) { - // Perspective --- - // convert from world to clip by multiplying with projection scaling factor - // to get the right thickness (see https://github.com/processing/processing/issues/5182) - - // The y value of the projection matrix may be flipped if rendering to a Framebuffer. - // Multiplying again by its sign here negates the flip to get just the scale. - curPerspScale = (uProjectionMatrix * vec4(1, sign(uProjectionMatrix[1][1]), 0, 0)).xy; - } else { - // No Perspective --- - // multiply by W (to cancel out division by W later in the pipeline) and - // convert from screen to clip (derived from clip to screen above) - curPerspScale = p.w / (0.5 * uViewport.zw); - } - - vec2 offset; - if (vJoin == 1.) { - vTangent = normalize(tangentIn + tangentOut); - vec2 normalIn = vec2(-tangentIn.y, tangentIn.x); - vec2 normalOut = vec2(-tangentOut.y, tangentOut.x); - float side = sign(aSide); - float sideEnum = abs(aSide); - - // We generate vertices for joins on either side of the centerline, but - // the "elbow" side is the only one needing a join. By not setting the - // offset for the other side, all its vertices will end up in the same - // spot and not render, effectively discarding it. - if (sign(dot(tangentOut, vec2(-tangentIn.y, tangentIn.x))) != side) { - // Side enums: - // 1: the side going into the join - // 2: the middle of the join - // 3: the side going out of the join - if (sideEnum == 2.) { - // Calculate the position + tangent on either side of the join, and - // find where the lines intersect to find the elbow of the join - vec2 c = (posp.xy/posp.w + vec2(1.,1.)) * 0.5 * uViewport.zw; - vec2 intersection = lineIntersection( - c + (side * normalIn * uStrokeWeight / 2.), - tangentIn, - c + (side * normalOut * uStrokeWeight / 2.), - tangentOut - ); - offset = (intersection - c); - - // When lines are thick and the angle of the join approaches 180, the - // elbow might be really far from the center. We'll apply a limit to - // the magnitude to avoid lines going across the whole screen when this - // happens. - float mag = length(offset); - float maxMag = 3. * uStrokeWeight; - if (mag > maxMag) { - offset *= maxMag / mag; - } - } else if (sideEnum == 1.) { - offset = side * normalIn * uStrokeWeight / 2.; - } else if (sideEnum == 3.) { - offset = side * normalOut * uStrokeWeight / 2.; - } - } - if (uStrokeJoin == STROKE_JOIN_BEVEL) { - vec2 avgNormal = vec2(-vTangent.y, vTangent.x); - vMaxDist = abs(dot(avgNormal, normalIn * uStrokeWeight / 2.)); - } else { - vMaxDist = uStrokeWeight / 2.; - } - } else { - vec2 tangent = aTangentIn == vec3(0.) ? tangentOut : tangentIn; - vTangent = tangent; - vec2 normal = vec2(-tangent.y, tangent.x); - - float normalOffset = sign(aSide); - // Caps will have side values of -2 or 2 on the edge of the cap that - // extends out from the line - float tangentOffset = abs(aSide) - 1.; - offset = (normal * normalOffset + tangent * tangentOffset) * - uStrokeWeight * 0.5; - vMaxDist = uStrokeWeight / 2.; - } - vPosition = vCenter + offset; - - gl_Position.xy = p.xy + offset.xy * curPerspScale; - gl_Position.zw = p.zw; - - vColor = (uUseLineColor ? aVertexColor : uMaterialColor); -} -`,lineFrag:I+`precision mediump int; - -uniform vec4 uMaterialColor; -uniform int uStrokeCap; -uniform int uStrokeJoin; -uniform float uStrokeWeight; - -IN vec4 vColor; -IN vec2 vTangent; -IN vec2 vCenter; -IN vec2 vPosition; -IN float vMaxDist; -IN float vCap; -IN float vJoin; - -float distSquared(vec2 a, vec2 b) { - vec2 aToB = b - a; - return dot(aToB, aToB); -} - -void main() { - if (vCap > 0.) { - if ( - uStrokeCap == STROKE_CAP_ROUND && - distSquared(vPosition, vCenter) > uStrokeWeight * uStrokeWeight * 0.25 - ) { - discard; - } else if ( - uStrokeCap == STROKE_CAP_SQUARE && - dot(vPosition - vCenter, vTangent) > 0. - ) { - discard; - } - // Use full area for PROJECT - } else if (vJoin > 0.) { - if ( - uStrokeJoin == STROKE_JOIN_ROUND && - distSquared(vPosition, vCenter) > uStrokeWeight * uStrokeWeight * 0.25 - ) { - discard; - } else if (uStrokeJoin == STROKE_JOIN_BEVEL) { - vec2 normal = vec2(-vTangent.y, vTangent.x); - if (abs(dot(vPosition - vCenter, normal)) > vMaxDist) { - discard; - } - } - // Use full area for MITER - } - OUT_COLOR = vec4(vColor.rgb, 1.) * vColor.a; -} -`,pointVert:`IN vec3 aPosition; -uniform float uPointSize; -OUT float vStrokeWeight; -uniform mat4 uModelViewMatrix; -uniform mat4 uProjectionMatrix; -void main() { - vec4 positionVec4 = vec4(aPosition, 1.0); - gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; - gl_PointSize = uPointSize; - vStrokeWeight = uPointSize; -} -`,pointFrag:`precision mediump int; -uniform vec4 uMaterialColor; -IN float vStrokeWeight; - -void main(){ - float mask = 0.0; - - // make a circular mask using the gl_PointCoord (goes from 0 - 1 on a point) - // might be able to get a nicer edge on big strokeweights with smoothstep but slightly less performant - - mask = step(0.98, length(gl_PointCoord * 2.0 - 1.0)); - - // if strokeWeight is 1 or less lets just draw a square - // this prevents weird artifacting from carving circles when our points are really small - // if strokeWeight is larger than 1, we just use it as is - - mask = mix(0.0, mask, clamp(floor(vStrokeWeight - 0.5),0.0,1.0)); - - // throw away the borders of the mask - // otherwise we get weird alpha blending issues - - if(mask > 0.98){ - discard; - } - - OUT_COLOR = vec4(uMaterialColor.rgb, 1.) * uMaterialColor.a; -} -`,imageLightVert:`precision highp float; -attribute vec3 aPosition; -attribute vec3 aNormal; -attribute vec2 aTexCoord; - -varying vec3 localPos; -varying vec3 vWorldNormal; -varying vec3 vWorldPosition; -varying vec2 vTexCoord; - -uniform mat4 uModelViewMatrix; -uniform mat4 uProjectionMatrix; -uniform mat3 uNormalMatrix; - -void main() { - // Multiply the position by the matrix. - vec4 viewModelPosition = uModelViewMatrix * vec4(aPosition, 1.0); - gl_Position = uProjectionMatrix * viewModelPosition; - - // orient the normals and pass to the fragment shader - vWorldNormal = uNormalMatrix * aNormal; - - // send the view position to the fragment shader - vWorldPosition = (uModelViewMatrix * vec4(aPosition, 1.0)).xyz; - - localPos = vWorldPosition; - vTexCoord = aTexCoord; -} - - -/* -in the vertex shader we'll compute the world position and world oriented normal of the vertices and pass those to the fragment shader as varyings. -*/ -`,imageLightDiffusedFrag:`precision highp float; -varying vec3 localPos; - -// the HDR cubemap converted (can be from an equirectangular environment map.) -uniform sampler2D environmentMap; -varying vec2 vTexCoord; - -const float PI = 3.14159265359; - -vec2 nTOE( vec3 v ){ - // x = r sin(phi) cos(theta) - // y = r cos(phi) - // z = r sin(phi) sin(theta) - float phi = acos( v.y ); - // if phi is 0, then there are no x, z components - float theta = 0.0; - // else - theta = acos(v.x / sin(phi)); - float sinTheta = v.z / sin(phi); - if (sinTheta < 0.0) { - // Turn it into -theta, but in the 0-2PI range - theta = 2.0 * PI - theta; - } - theta = theta / (2.0 * 3.14159); - phi = phi / 3.14159 ; - - vec2 angles = vec2( phi, theta ); - return angles; -} - -float random(vec2 p) { - vec3 p3 = fract(vec3(p.xyx) * .1031); - p3 += dot(p3, p3.yzx + 33.33); - return fract((p3.x + p3.y) * p3.z); -} - -void main() -{ - // the sample direction equals the hemisphere's orientation - float phi = vTexCoord.x * 2.0 * PI; - float theta = vTexCoord.y * PI; - float x = sin(theta) * cos(phi); - float y = sin(theta) * sin(phi); - float z = cos(theta); - vec3 normal = vec3( x, y, z); - - // Discretely sampling the hemisphere given the integral's - // spherical coordinates translates to the following fragment code: - vec3 irradiance = vec3(0.0); - vec3 up = vec3(0.0, 1.0, 0.0); - vec3 right = normalize(cross(up, normal)); - up = normalize(cross(normal, right)); - - // We specify a fixed sampleDelta delta value to traverse - // the hemisphere; decreasing or increasing the sample delta - // will increase or decrease the accuracy respectively. - const float sampleDelta = 0.100; - float nrSamples = 0.0; - float randomOffset = random(gl_FragCoord.xy) * sampleDelta; - for(float rawPhi = 0.0; rawPhi < 2.0 * PI; rawPhi += sampleDelta) - { - float phi = rawPhi + randomOffset; - for(float rawTheta = 0.0; rawTheta < ( 0.5 ) * PI; rawTheta += sampleDelta) - { - float theta = rawTheta + randomOffset; - // spherical to cartesian (in tangent space) // tangent space to world // add each sample result to irradiance - float x = sin(theta) * cos(phi); - float y = sin(theta) * sin(phi); - float z = cos(theta); - vec3 tangentSample = vec3( x, y, z); - - vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * normal; - irradiance += (texture2D(environmentMap, nTOE(sampleVec)).xyz) * cos(theta) * sin(theta); - nrSamples++; - } - } - // divide by the total number of samples taken, giving us the average sampled irradiance. - irradiance = PI * irradiance * (1.0 / float(nrSamples )) ; - - - gl_FragColor = vec4(irradiance, 1.0); -}`,imageLightSpecularFrag:`precision highp float;\r -varying vec3 localPos;\r -varying vec2 vTexCoord;\r -\r -// our texture\r -uniform sampler2D environmentMap;\r -uniform float roughness;\r -\r -const float PI = 3.14159265359;\r -\r -float VanDerCorput(int bits);\r -vec2 HammersleyNoBitOps(int i, int N);\r -vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness);\r -\r -\r -vec2 nTOE( vec3 v ){\r - // x = r sin(phi) cos(theta) \r - // y = r cos(phi) \r - // z = r sin(phi) sin(theta)\r - float phi = acos( v.y );\r - // if phi is 0, then there are no x, z components\r - float theta = 0.0;\r - // else \r - theta = acos(v.x / sin(phi));\r - float sinTheta = v.z / sin(phi);\r - if (sinTheta < 0.0) {\r - // Turn it into -theta, but in the 0-2PI range\r - theta = 2.0 * PI - theta;\r - }\r - theta = theta / (2.0 * 3.14159);\r - phi = phi / 3.14159 ;\r - \r - vec2 angles = vec2( phi, theta );\r - return angles;\r -}\r -\r -\r -void main(){\r - const int SAMPLE_COUNT = 400; // 4096\r - int lowRoughnessLimit = int(pow(2.0,(roughness+0.1)*20.0));\r - float totalWeight = 0.0;\r - vec3 prefilteredColor = vec3(0.0);\r - float phi = vTexCoord.x * 2.0 * PI;\r - float theta = vTexCoord.y * PI;\r - float x = sin(theta) * cos(phi);\r - float y = sin(theta) * sin(phi);\r - float z = cos(theta);\r - vec3 N = vec3(x,y,z);\r - vec3 V = N;\r - for (int i = 0; i < SAMPLE_COUNT; ++i)\r - {\r - // break at smaller sample numbers for low roughness levels\r - if(i == lowRoughnessLimit)\r - {\r - break;\r - }\r - vec2 Xi = HammersleyNoBitOps(i, SAMPLE_COUNT);\r - vec3 H = ImportanceSampleGGX(Xi, N, roughness);\r - vec3 L = normalize(2.0 * dot(V, H) * H - V);\r -\r - float NdotL = max(dot(N, L), 0.0);\r - if (NdotL > 0.0)\r - {\r - prefilteredColor += texture2D(environmentMap, nTOE(L)).xyz * NdotL;\r - totalWeight += NdotL;\r - }\r - }\r - prefilteredColor = prefilteredColor / totalWeight;\r -\r - gl_FragColor = vec4(prefilteredColor, 1.0);\r -}\r -\r -vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness){\r - float a = roughness * roughness;\r -\r - float phi = 2.0 * PI * Xi.x;\r - float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));\r - float sinTheta = sqrt(1.0 - cosTheta * cosTheta);\r - // from spherical coordinates to cartesian coordinates\r - vec3 H;\r - H.x = cos(phi) * sinTheta;\r - H.y = sin(phi) * sinTheta;\r - H.z = cosTheta;\r -\r - // from tangent-space vector to world-space sample vector\r - vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);\r - vec3 tangent = normalize(cross(up, N));\r - vec3 bitangent = cross(N, tangent);\r -\r - vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;\r - return normalize(sampleVec);\r -}\r -\r -\r -float VanDerCorput(int n, int base)\r -{\r -#ifdef WEBGL2\r -\r - uint bits = uint(n);\r - bits = (bits << 16u) | (bits >> 16u);\r - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);\r - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);\r - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);\r - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);\r - return float(bits) * 2.3283064365386963e-10; // / 0x100000000\r -\r -#else\r -\r - float invBase = 1.0 / float(base);\r - float denom = 1.0;\r - float result = 0.0;\r -\r -\r - for (int i = 0; i < 32; ++i)\r - {\r - if (n > 0)\r - {\r - denom = mod(float(n), 2.0);\r - result += denom * invBase;\r - invBase = invBase / 2.0;\r - n = int(float(n) / 2.0);\r - }\r - }\r -\r -\r - return result;\r -\r -#endif\r -}\r -\r -vec2 HammersleyNoBitOps(int i, int N)\r -{\r - return vec2(float(i) / float(N), VanDerCorput(i, 2));\r -}\r -`},F=N.sphereMappingFrag;for(O in N)N[O]=`#ifdef WEBGL2 - -#define IN in -#define OUT out - -#ifdef FRAGMENT_SHADER -out vec4 outColor; -#define OUT_COLOR outColor -#endif -#define TEXTURE texture - -#else - -#ifdef FRAGMENT_SHADER -#define IN varying -#else -#define IN attribute -#endif -#define OUT varying -#define TEXTURE texture2D - -#ifdef FRAGMENT_SHADER -#define OUT_COLOR gl_FragColor -#endif - -#endif -`+N[O];M(A={},f.GRAY,`precision highp float; - -varying vec2 vTexCoord; - -uniform sampler2D tex0; - -float luma(vec3 color) { - // weighted grayscale with luminance values - return dot(color, vec3(0.2126, 0.7152, 0.0722)); -} - -void main() { - vec4 tex = texture2D(tex0, vTexCoord); - float gray = luma(tex.rgb); - gl_FragColor = vec4(gray, gray, gray, tex.a); -} -`),M(A,f.ERODE,`// Reduces the bright areas in an image - -precision highp float; - -varying vec2 vTexCoord; - -uniform sampler2D tex0; -uniform vec2 texelSize; - -float luma(vec3 color) { - // weighted grayscale with luminance values - // weights 77, 151, 28 taken from src/image/filters.js - return dot(color, vec3(0.300781, 0.589844, 0.109375)); -} - -void main() { - vec4 color = texture2D(tex0, vTexCoord); - float lum = luma(color.rgb); - - // set current color as the darkest neighbor color - - vec4 neighbors[4]; - neighbors[0] = texture2D(tex0, vTexCoord + vec2( texelSize.x, 0.0)); - neighbors[1] = texture2D(tex0, vTexCoord + vec2(-texelSize.x, 0.0)); - neighbors[2] = texture2D(tex0, vTexCoord + vec2(0.0, texelSize.y)); - neighbors[3] = texture2D(tex0, vTexCoord + vec2(0.0, -texelSize.y)); - - for (int i = 0; i < 4; i++) { - vec4 neighborColor = neighbors[i]; - float neighborLum = luma(neighborColor.rgb); - - if (neighborLum < lum) { - color = neighborColor; - lum = neighborLum; - } - } - - gl_FragColor = color; -} -`),M(A,f.DILATE,`// Increase the bright areas in an image - -precision highp float; - -varying vec2 vTexCoord; - -uniform sampler2D tex0; -uniform vec2 texelSize; - -float luma(vec3 color) { - // weighted grayscale with luminance values - // weights 77, 151, 28 taken from src/image/filters.js - return dot(color, vec3(0.300781, 0.589844, 0.109375)); -} - -void main() { - vec4 color = texture2D(tex0, vTexCoord); - float lum = luma(color.rgb); - - // set current color as the brightest neighbor color - - vec4 neighbors[4]; - neighbors[0] = texture2D(tex0, vTexCoord + vec2( texelSize.x, 0.0)); - neighbors[1] = texture2D(tex0, vTexCoord + vec2(-texelSize.x, 0.0)); - neighbors[2] = texture2D(tex0, vTexCoord + vec2(0.0, texelSize.y)); - neighbors[3] = texture2D(tex0, vTexCoord + vec2(0.0, -texelSize.y)); - - for (int i = 0; i < 4; i++) { - vec4 neighborColor = neighbors[i]; - float neighborLum = luma(neighborColor.rgb); - - if (neighborLum > lum) { - color = neighborColor; - lum = neighborLum; - } - } - - gl_FragColor = color; -} -`),M(A,f.BLUR,`precision highp float; - -// Two-pass blur filter, unweighted kernel. -// See also a similar blur at Adam Ferriss' repo of shader examples: -// https://github.com/aferriss/p5jsShaderExamples/blob/gh-pages/4_image-effects/4-9_single-pass-blur/effect.frag - - -uniform sampler2D tex0; -varying vec2 vTexCoord; -uniform vec2 direction; -uniform vec2 canvasSize; -uniform float radius; - -float random(vec2 p) { - vec3 p3 = fract(vec3(p.xyx) * .1031); - p3 += dot(p3, p3.yzx + 33.33); - return fract((p3.x + p3.y) * p3.z); -} - -// This isn't a real Gaussian weight, it's a quadratic weight. It's what the -// CPU mode's blur uses though, so we also use it here to match. -float quadWeight(float x, float e) { - return pow(e-abs(x), 2.); -} - -void main(){ - vec2 uv = vTexCoord; - - // A reasonable maximum number of samples - const float maxSamples = 64.0; - - float numSamples = floor(7. * radius); - if (fract(numSamples / 2.) == 0.) { - numSamples++; - } - vec4 avg = vec4(0.0); - float total = 0.0; - - // Calculate the spacing to avoid skewing if numSamples > maxSamples - float spacing = 1.0; - if (numSamples > maxSamples) { - spacing = numSamples / maxSamples; - numSamples = maxSamples; - } - - float randomOffset = (spacing - 1.0) * mix(-0.5, 0.5, random(gl_FragCoord.xy)); - for (float i = 0.0; i < maxSamples; i++) { - if (i >= numSamples) break; - - float sample = i * spacing - (numSamples - 1.0) * 0.5 * spacing + randomOffset; - vec2 sampleCoord = uv + vec2(sample, sample) / canvasSize * direction; - float weight = quadWeight(sample, (numSamples - 1.0) * 0.5 * spacing); - - avg += weight * texture2D(tex0, sampleCoord); - total += weight; - } - - avg /= total; - gl_FragColor = avg; -} -`),M(A,f.POSTERIZE,`// Limit color space for a stylized cartoon / poster effect - -precision highp float; - -varying vec2 vTexCoord; - -uniform sampler2D tex0; -uniform float filterParameter; - -vec3 quantize(vec3 color, float n) { - // restrict values to N options/bins - // and floor each channel to nearest value - // - // eg. when N = 5, values = 0.0, 0.25, 0.50, 0.75, 1.0 - // then quantize (0.1, 0.7, 0.9) -> (0.0, 0.5, 1.0) - - color = color * n; - color = floor(color); - color = color / (n - 1.0); - return color; -} - -void main() { - vec4 color = texture2D(tex0, vTexCoord); - - vec3 restrictedColor = quantize(color.rgb / color.a, filterParameter); - - gl_FragColor = vec4(restrictedColor.rgb * color.a, color.a); -} -`),M(A,f.OPAQUE,`// Set alpha channel to entirely opaque - -precision highp float; - -varying vec2 vTexCoord; - -uniform sampler2D tex0; - -void main() { - vec4 color = texture2D(tex0, vTexCoord); - gl_FragColor = vec4(color.rgb / color.a, 1.0); -} -`),M(A,f.INVERT,`// Set each pixel to inverse value -// Note that original INVERT does not change the opacity, so this follows suit - -precision highp float; - -varying vec2 vTexCoord; - -uniform sampler2D tex0; - -void main() { -vec4 color = texture2D(tex0, vTexCoord); -vec3 origColor = color.rgb / color.a; -vec3 invertedColor = vec3(1.0) - origColor; -gl_FragColor = vec4(invertedColor * color.a, color.a); -} -`),M(A,f.THRESHOLD,`// Convert pixels to either white or black, -// depending on if their luma is above or below filterParameter - -precision highp float; - -varying vec2 vTexCoord; - -uniform sampler2D tex0; -uniform float filterParameter; - -float luma(vec3 color) { - // weighted grayscale with luminance values - return dot(color, vec3(0.2126, 0.7152, 0.0722)); -} - -void main() { - vec4 color = texture2D(tex0, vTexCoord); - float gray = luma(color.rgb / color.a); - // floor() used to match src/image/filters.js - float threshold = floor(filterParameter * 255.0) / 255.0; - float blackOrWhite = step(threshold, gray); - gl_FragColor = vec4(vec3(blackOrWhite) * color.a, color.a); -} -`);var B=A;function W(V,K,ue,le,T,D,G,q,Z,ee){var ne=K.getParameter(K.FRAMEBUFFER_BINDING),ue=(K.bindFramebuffer(K.FRAMEBUFFER,ue),q===K.RGBA?4:3),ie=D*G*ue,he=Z===K.UNSIGNED_BYTE?Uint8Array:Float32Array;if(V instanceof he&&V.length===ie||(V=new he(ie)),K.readPixels(le,ee?ee-T-G:T,D,G,q,Z,V),K.bindFramebuffer(K.FRAMEBUFFER,ne),ee)for(var $=Math.floor(G/2),z=new he(D*ue),te=0;te<$;te++){var ce=te*D*4,me=(G-te-1)*D*4;z.set(V.subarray(ce,ce+4*D)),V.copyWithin(ce,me,me+4*D),V.set(z,me)}return V}function H(V,Z,J,le,T,D,G){var q=V.getParameter(V.FRAMEBUFFER_BINDING),Z=(V.bindFramebuffer(V.FRAMEBUFFER,Z),T===V.RGBA?4:3),Z=new(D===V.UNSIGNED_BYTE?Uint8Array:Float32Array)(Z);return V.readPixels(J,G?G-le-1:le,1,1,T,D,Z),V.bindFramebuffer(V.FRAMEBUFFER,q),Array.from(Z)}o.default.prototype.setAttributes=function(V,K){if(this._glAttributes===void 0)console.log("You are trying to use setAttributes on a p5.Graphics object that does not use a WEBGL renderer.");else{var J=!0;if(K!==void 0?(this._glAttributes===null&&(this._glAttributes={}),this._glAttributes[V]!==K&&(this._glAttributes[V]=K,J=!1)):V instanceof Object&&this._glAttributes!==V&&(this._glAttributes=V,J=!1),this._renderer.isP3D&&!J){if(!this._setupDone){for(var le in this._renderer.retainedMode.geometry)if(this._renderer.retainedMode.geometry.hasOwnProperty(le))return void o.default._friendlyError("Sorry, Could not set the attributes, you need to call setAttributes() before calling the other drawing methods in setup()")}this.push(),this._renderer._resetContext(),this.pop(),this._renderer._curCamera&&(this._renderer._curCamera._renderer=this._renderer)}}},o.default.RendererGL=function(V){var K=le;if(typeof V!="function"&&V!==null)throw new TypeError("Super expression must either be null or a function");K.prototype=Object.create(V&&V.prototype,{constructor:{value:K,writable:!0,configurable:!0}}),V&&c(K,V);var J=p(le);function le(T,D,G,q){if(this instanceof le)return(T=J.call(this,T,D,G))._setAttributeDefaults(D),T._initContext(),T.isP3D=!0,T.geometryBuilder=void 0,T.GL=T.drawingContext,T._pInst._setProperty("drawingContext",T.drawingContext),T._isErasing=!1,T._clipDepths=[],T._isClipApplied=!1,T._stencilTestOn=!1,T._enableLighting=!1,T.ambientLightColors=[],T.mixedAmbientLight=[],T.mixedSpecularColor=[],T.specularColors=[1,1,1],T.directionalLightDirections=[],T.directionalLightDiffuseColors=[],T.directionalLightSpecularColors=[],T.pointLightPositions=[],T.pointLightDiffuseColors=[],T.pointLightSpecularColors=[],T.spotLightPositions=[],T.spotLightDirections=[],T.spotLightDiffuseColors=[],T.spotLightSpecularColors=[],T.spotLightAngle=[],T.spotLightConc=[],T.activeImageLight=null,T.diffusedTextures=new Map,T.specularTextures=new Map,T.drawMode=f.FILL,T.curFillColor=T._cachedFillStyle=[1,1,1,1],T.curAmbientColor=T._cachedFillStyle=[1,1,1,1],T.curSpecularColor=T._cachedFillStyle=[0,0,0,0],T.curEmissiveColor=T._cachedFillStyle=[0,0,0,0],T.curStrokeColor=T._cachedStrokeStyle=[0,0,0,1],T.curBlendMode=f.BLEND,T.preEraseBlend=void 0,T._cachedBlendMode=void 0,T.webglVersion===f.WEBGL2?T.blendExt=T.GL:T.blendExt=T.GL.getExtension("EXT_blend_minmax"),T._isBlending=!1,T._hasSetAmbient=!1,T._useSpecularMaterial=!1,T._useEmissiveMaterial=!1,T._useNormalMaterial=!1,T._useShininess=1,T._useMetalness=0,T._useLineColor=!1,T._useVertexColor=!1,T.registerEnabled=new Set,T._tint=[255,255,255,255],T.constantAttenuation=1,T.linearAttenuation=0,T.quadraticAttenuation=0,T.uModelMatrix=new o.default.Matrix,T.uViewMatrix=new o.default.Matrix,T.uMVMatrix=new o.default.Matrix,T.uPMatrix=new o.default.Matrix,T.uNMatrix=new o.default.Matrix("mat3"),T.curMatrix=new o.default.Matrix("mat3"),T._currentNormal=new o.default.Vector(0,0,1),T._curCamera=new o.default.Camera(b(T)),T._curCamera._computeCameraDefaultSettings(),T._curCamera._setDefaultCamera(),T.filterCamera=new o.default.Camera(b(T)),T.filterCamera._computeCameraDefaultSettings(),T.filterCamera._setDefaultCamera(),T.prevTouches=[],T.zoomVelocity=0,T.rotateVelocity=new o.default.Vector(0,0),T.moveVelocity=new o.default.Vector(0,0),T.executeZoom=!1,T.executeRotateAndMove=!1,T.specularShader=void 0,T.sphereMapping=void 0,T.diffusedShader=void 0,T._defaultLightShader=void 0,T._defaultImmediateModeShader=void 0,T._defaultNormalShader=void 0,T._defaultColorShader=void 0,T._defaultPointShader=void 0,T.userFillShader=void 0,T.userStrokeShader=void 0,T.userPointShader=void 0,T.retainedMode={geometry:{},buffers:{stroke:[new o.default.RenderBuffer(4,"lineVertexColors","lineColorBuffer","aVertexColor",b(T)),new o.default.RenderBuffer(3,"lineVertices","lineVerticesBuffer","aPosition",b(T)),new o.default.RenderBuffer(3,"lineTangentsIn","lineTangentsInBuffer","aTangentIn",b(T)),new o.default.RenderBuffer(3,"lineTangentsOut","lineTangentsOutBuffer","aTangentOut",b(T)),new o.default.RenderBuffer(1,"lineSides","lineSidesBuffer","aSide",b(T))],fill:[new o.default.RenderBuffer(3,"vertices","vertexBuffer","aPosition",b(T),T._vToNArray),new o.default.RenderBuffer(3,"vertexNormals","normalBuffer","aNormal",b(T),T._vToNArray),new o.default.RenderBuffer(4,"vertexColors","colorBuffer","aVertexColor",b(T)),new o.default.RenderBuffer(3,"vertexAmbients","ambientBuffer","aAmbientColor",b(T)),new o.default.RenderBuffer(2,"uvs","uvBuffer","aTexCoord",b(T),T._flatten)],text:[new o.default.RenderBuffer(3,"vertices","vertexBuffer","aPosition",b(T),T._vToNArray),new o.default.RenderBuffer(2,"uvs","uvBuffer","aTexCoord",b(T),T._flatten)]}},T.immediateMode={geometry:new o.default.Geometry,shapeMode:f.TRIANGLE_FAN,contourIndices:[],_bezierVertex:[],_quadraticVertex:[],_curveVertex:[],buffers:{fill:[new o.default.RenderBuffer(3,"vertices","vertexBuffer","aPosition",b(T),T._vToNArray),new o.default.RenderBuffer(3,"vertexNormals","normalBuffer","aNormal",b(T),T._vToNArray),new o.default.RenderBuffer(4,"vertexColors","colorBuffer","aVertexColor",b(T)),new o.default.RenderBuffer(3,"vertexAmbients","ambientBuffer","aAmbientColor",b(T)),new o.default.RenderBuffer(2,"uvs","uvBuffer","aTexCoord",b(T),T._flatten)],stroke:[new o.default.RenderBuffer(4,"lineVertexColors","lineColorBuffer","aVertexColor",b(T)),new o.default.RenderBuffer(3,"lineVertices","lineVerticesBuffer","aPosition",b(T)),new o.default.RenderBuffer(3,"lineTangentsIn","lineTangentsInBuffer","aTangentIn",b(T)),new o.default.RenderBuffer(3,"lineTangentsOut","lineTangentsOutBuffer","aTangentOut",b(T)),new o.default.RenderBuffer(1,"lineSides","lineSidesBuffer","aSide",b(T))],point:T.GL.createBuffer()}},T.pointSize=5,T.curStrokeWeight=1,T.curStrokeCap=f.ROUND,T.curStrokeJoin=f.ROUND,T.textures=new Map,T.framebuffers=new Set,T.activeFramebuffers=[],T.filterShader=void 0,T.filterLayer=void 0,T.filterLayerTemp=void 0,T.defaultFilterShaders={},T.textureMode=f.IMAGE,T.textureWrapX=f.CLAMP,T.textureWrapY=f.CLAMP,T._tex=null,T._curveTightness=6,T._lookUpTableBezier=[],T._lookUpTableQuadratic=[],T._lutBezierDetail=0,T._lutQuadraticDetail=0,T.isProcessingVertices=!1,T._tessy=T._initTessy(),T.fontInfos={},T._curShader=void 0,T;throw new TypeError("Cannot call a class as a function")}return K=le,(V=[{key:"beginGeometry",value:function(){if(this.geometryBuilder)throw new Error("It looks like `beginGeometry()` is being called while another p5.Geometry is already being build.");this.geometryBuilder=new g.default(this)}},{key:"endGeometry",value:function(){var T;if(this.geometryBuilder)return T=this.geometryBuilder.finish(),this.geometryBuilder=void 0,T;throw new Error("Make sure you call beginGeometry() before endGeometry()!")}},{key:"buildGeometry",value:function(T){return this.beginGeometry(),T(),this.endGeometry()}},{key:"_setAttributeDefaults",value:function(T){var D={alpha:!0,depth:!0,stencil:!0,antialias:navigator.userAgent.toLowerCase().includes("safari"),premultipliedAlpha:!0,preserveDrawingBuffer:!0,perPixelLighting:!0,version:2};T._glAttributes===null?T._glAttributes=D:T._glAttributes=Object.assign(D,T._glAttributes)}},{key:"_initContext",value:function(){if(this._pInst._glAttributes.version!==1&&(this.drawingContext=this.canvas.getContext("webgl2",this._pInst._glAttributes)),this.webglVersion=this.drawingContext?f.WEBGL2:f.WEBGL,this._pInst._setProperty("webglVersion",this.webglVersion),this.drawingContext||(this.drawingContext=this.canvas.getContext("webgl",this._pInst._glAttributes)||this.canvas.getContext("experimental-webgl",this._pInst._glAttributes)),this.drawingContext===null)throw new Error("Error creating webgl context");var T=this.drawingContext;T.enable(T.DEPTH_TEST),T.depthFunc(T.LEQUAL),T.viewport(0,0,T.drawingBufferWidth,T.drawingBufferHeight),T.pixelStorei(T.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!0),this._viewport=this.drawingContext.getParameter(this.drawingContext.VIEWPORT)}},{key:"_getParam",value:function(){var T=this.drawingContext;return T.getParameter(T.MAX_TEXTURE_SIZE)}},{key:"_adjustDimensions",value:function(T,D){this._maxTextureSize||(this._maxTextureSize=this._getParam());var q=this._maxTextureSize,q=(o.default.prototype._maxAllowedPixelDimensions,Math.floor(q/this.pixelDensity())),G=Math.min(T,q),q=Math.min(D,q);return G===T&&q===D||console.warn("Warning: The requested width/height exceeds hardware limits. "+"Adjusting dimensions to width: ".concat(G,", height: ").concat(q,".")),{adjustedWidth:G,adjustedHeight:q}}},{key:"_resetContext",value:function(T,D){var G,q=this.width,Z=this.height,ne=this.canvas.id,ee=this._pInst instanceof o.default.Graphics,ne=(ee?((G=this._pInst).canvas.parentNode.removeChild(G.canvas),G.canvas=document.createElement("canvas"),(G._pInst._userNode||document.body).appendChild(G.canvas),o.default.Element.call(G,G.canvas,G._pInst),G.width=q,G.height=Z):((G=this.canvas)&&G.parentNode.removeChild(G),(G=document.createElement("canvas")).id=ne,(this._pInst._userNode||document.body).appendChild(G),this._pInst.canvas=G,this.canvas=G),new o.default.RendererGL(this._pInst.canvas,this._pInst,!ee));this._pInst._setProperty("_renderer",ne),ne.resize(q,Z),ne._applyDefaults(),ee||this._pInst._elements.push(ne),typeof D=="function"&&setTimeout(function(){D.apply(window._renderer,T)},0)}},{key:"_update",value:function(){this.uModelMatrix.reset(),this.uViewMatrix.set(this._curCamera.cameraMatrix),this.ambientLightColors.length=0,this.specularColors=[1,1,1],this.directionalLightDirections.length=0,this.directionalLightDiffuseColors.length=0,this.directionalLightSpecularColors.length=0,this.pointLightPositions.length=0,this.pointLightDiffuseColors.length=0,this.pointLightSpecularColors.length=0,this.spotLightPositions.length=0,this.spotLightDirections.length=0,this.spotLightDiffuseColors.length=0,this.spotLightSpecularColors.length=0,this.spotLightAngle.length=0,this.spotLightConc.length=0,this._enableLighting=!1,this._tint=[255,255,255,255],this.GL.clearStencil(0),this.GL.clear(this.GL.DEPTH_BUFFER_BIT|this.GL.STENCIL_BUFFER_BIT),this.GL.disable(this.GL.STENCIL_TEST)}},{key:"background",value:function(){var q=(q=this._pInst).color.apply(q,arguments),T=q.levels[0]/255,D=q.levels[1]/255,G=q.levels[2]/255,q=q.levels[3]/255;this.clear(T,D,G,q)}},{key:"fill",value:function(T,D,G,q){var Z=o.default.prototype.color.apply(this._pInst,arguments);this.curFillColor=Z._array,this.drawMode=f.FILL,this._useNormalMaterial=!1,this._tex=null}},{key:"stroke",value:function(T,D,G,q){var Z=o.default.prototype.color.apply(this._pInst,arguments);this.curStrokeColor=Z._array}},{key:"strokeCap",value:function(T){this.curStrokeCap=T}},{key:"strokeJoin",value:function(T){this.curStrokeJoin=T}},{key:"getFilterLayer",value:function(){return this.filterLayer||(this.filterLayer=this._pInst.createFramebuffer()),this.filterLayer}},{key:"getFilterLayerTemp",value:function(){return this.filterLayerTemp||(this.filterLayerTemp=this._pInst.createFramebuffer()),this.filterLayerTemp}},{key:"matchSize",value:function(T,D){T.width===D.width&&T.height===D.height||T.resize(D.width,D.height),T.pixelDensity()!==D.pixelDensity()&&T.pixelDensity(D.pixelDensity())}},{key:"filter",value:function(){var T,D,G=this,q=this.getFilterLayer(),Z=void 0,ee=void 0,ne=(typeof(arguments.length<=0?void 0:arguments[0])=="string"?(ee=arguments.length<=0?void 0:arguments[0],M(T={},f.BLUR,3),M(T,f.POSTERIZE,4),M(T,f.THRESHOLD,.5),Z=ee in(T=T)&&(arguments.length<=1?void 0:arguments[1])===void 0?T[ee]:arguments.length<=1?void 0:arguments[1],ee in this.defaultFilterShaders||(this.defaultFilterShaders[ee]=new o.default.Shader(q._renderer,`uniform mat4 uModelViewMatrix; -uniform mat4 uProjectionMatrix; - -attribute vec3 aPosition; -// texcoords only come from p5 to vertex shader -// so pass texcoords on to the fragment shader in a varying variable -attribute vec2 aTexCoord; -varying vec2 vTexCoord; - -void main() { - // transferring texcoords for the frag shader - vTexCoord = aTexCoord; - - // copy position with a fourth coordinate for projection (1.0 is normal) - vec4 positionVec4 = vec4(aPosition, 1.0); - - gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; -} -`,B[ee])),this.filterShader=this.defaultFilterShaders[ee]):this.filterShader=arguments.length<=0?void 0:arguments[0],this.activeFramebuffer()||this),ue=(this.matchSize(q,ne),q.draw(function(){return G._pInst.clear()}),[1/(ne.width*ne.pixelDensity()),1/(ne.height*ne.pixelDensity())]);ee===f.BLUR?(D=this.getFilterLayerTemp(),this.matchSize(D,ne),this._pInst.push(),this._pInst.noStroke(),this._pInst.blendMode(f.BLEND),this._pInst.shader(this.filterShader),this.filterShader.setUniform("texelSize",ue),this.filterShader.setUniform("canvasSize",[ne.width,ne.height]),this.filterShader.setUniform("radius",Math.max(1,Z)),D.draw(function(){G.filterShader.setUniform("direction",[1,0]),G.filterShader.setUniform("tex0",ne),G._pInst.clear(),G._pInst.shader(G.filterShader),G._pInst.noLights(),G._pInst.plane(ne.width,ne.height)}),q.draw(function(){G.filterShader.setUniform("direction",[0,1]),G.filterShader.setUniform("tex0",D),G._pInst.clear(),G._pInst.shader(G.filterShader),G._pInst.noLights(),G._pInst.plane(ne.width,ne.height)}),this._pInst.pop()):q.draw(function(){G._pInst.noStroke(),G._pInst.blendMode(f.BLEND),G._pInst.shader(G.filterShader),G.filterShader.setUniform("tex0",ne),G.filterShader.setUniform("texelSize",ue),G.filterShader.setUniform("canvasSize",[ne.width,ne.height]),G.filterShader.setUniform("filterParameter",Z),G._pInst.noLights(),G._pInst.plane(ne.width,ne.height)}),this._pInst.push(),this._pInst.noStroke(),this.clear(),this._pInst.push(),this._pInst.imageMode(f.CORNER),this._pInst.blendMode(f.BLEND),ne.filterCamera._resize(),this._pInst.setCamera(ne.filterCamera),this._pInst.resetMatrix(),this._pInst.image(q,-ne.width/2,-ne.height/2,ne.width,ne.height),this._pInst.clearDepth(),this._pInst.pop(),this._pInst.pop()}},{key:"pixelDensity",value:function(T){return T?this._pInst.pixelDensity(T):this._pInst.pixelDensity()}},{key:"blendMode",value:function(T){T===f.DARKEST||T===f.LIGHTEST||T===f.ADD||T===f.BLEND||T===f.SUBTRACT||T===f.SCREEN||T===f.EXCLUSION||T===f.REPLACE||T===f.MULTIPLY||T===f.REMOVE?this.curBlendMode=T:T!==f.BURN&&T!==f.OVERLAY&&T!==f.HARD_LIGHT&&T!==f.SOFT_LIGHT&&T!==f.DODGE||console.warn("BURN, OVERLAY, HARD_LIGHT, SOFT_LIGHT, and DODGE only work for blendMode in 2D mode.")}},{key:"erase",value:function(T,D){this._isErasing||(this.preEraseBlend=this.curBlendMode,this._isErasing=!0,this.blendMode(f.REMOVE),this._cachedFillStyle=this.curFillColor.slice(),this.curFillColor=[1,1,1,T/255],this._cachedStrokeStyle=this.curStrokeColor.slice(),this.curStrokeColor=[1,1,1,D/255])}},{key:"noErase",value:function(){this._isErasing&&(this.curFillColor=this._cachedFillStyle.slice(),this.curStrokeColor=this._cachedStrokeStyle.slice(),this.curBlendMode=this.preEraseBlend,this.blendMode(this.preEraseBlend),this._isErasing=!1,this._applyBlendMode())}},{key:"drawTarget",value:function(){return this.activeFramebuffers[this.activeFramebuffers.length-1]||this}},{key:"beginClip",value:function(){var T=0>7,127&we,ae>>7,127&ae);for(var Se=0;Se>7,127&Pe,0,0)}}return{cellImageInfo:re,dimOffset:Ie,dimImageInfo:xe}}}}]),p}();f.default.RendererGL.prototype._renderText=function(p,b,j,M,E){if(this._textFont&&typeof this._textFont!="string"){if(!(E<=M)&&this._doFill){if(this._isOpenType()){p.push();var E=this._doStroke,k=this.drawMode,O=(this._doStroke=!1,this.drawMode=g.TEXTURE,this._textFont.font),L=(L=this._textFont._fontInfo)||(this._textFont._fontInfo=new c(O)),j=this._textFont._handleAlignment(this,b,j,M),M=this._textSize/O.unitsPerEm,C=(this.translate(j.x,j.y,0),this.scale(M,M,1),this.GL),j=!this._defaultFontShader,I=this._getFontShader(),A=(I.init(),I.bindShader(),j&&(I.setUniform("uGridImageSize",[64,64]),I.setUniform("uCellsImageSize",[64,64]),I.setUniform("uStrokeImageSize",[64,64]),I.setUniform("uGridSize",[9,9])),this._applyColorBlend(this.curFillColor),this.retainedMode.geometry.glyph),N=(A||((M=this._textGeom=new f.default.Geometry(1,1,function(){for(var he=0;he<=1;he++)for(var $=0;$<=1;$++)this.vertices.push(new f.default.Vector($,he,0)),this.uvs.push($,he)})).computeFaces().computeNormals(),A=this.createBuffers("glyph",M)),!0),j=!1,M=void 0;try{for(var F,B=this.retainedMode.buffers.text[Symbol.iterator]();!(N=(F=B.next()).done);N=!0)F.value._prepareBuffer(A,I)}catch(he){j=!0,M=he}finally{try{N||B.return==null||B.return()}finally{if(j)throw M}}this._bindBuffer(A.indexBuffer,C.ELEMENT_ARRAY_BUFFER),I.setUniform("uMaterialColor",this.curFillColor),C.pixelStorei(C.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1);try{var W=0,H=null,V=O.stringToGlyphs(b),K=!0,J=!1,le=void 0;try{for(var T,D=V[Symbol.iterator]();!(K=(T=D.next()).done);K=!0){var G,q,Z=T.value,ee=(H&&(W+=O.getKerningValue(H,Z)),L.getGlyphInfo(Z));ee.uGlyphRect&&(G=ee.rowInfo,q=ee.colInfo,I.setUniform("uSamplerStrokes",ee.strokeImageInfo.imageData),I.setUniform("uSamplerRowStrokes",G.cellImageInfo.imageData),I.setUniform("uSamplerRows",G.dimImageInfo.imageData),I.setUniform("uSamplerColStrokes",q.cellImageInfo.imageData),I.setUniform("uSamplerCols",q.dimImageInfo.imageData),I.setUniform("uGridOffset",ee.uGridOffset),I.setUniform("uGlyphRect",ee.uGlyphRect),I.setUniform("uGlyphOffset",W),I.bindTextures(),C.drawElements(C.TRIANGLES,6,this.GL.UNSIGNED_SHORT,0)),W+=Z.advanceWidth,H=Z}}catch(he){J=!0,le=he}finally{try{K||D.return==null||D.return()}finally{if(J)throw le}}}finally{I.unbindShader(),this._doStroke=E,this.drawMode=k,C.pixelStorei(C.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!0),p.pop()}}else console.log("WEBGL: only Opentype (.otf) and Truetype (.ttf) fonts are supported");return p}}else console.log("WEBGL: you must load and set a font before drawing text. See `loadFont` and `textFont` for more details.")}},{"../core/constants":272,"../core/main":283,"./p5.RendererGL.Retained":340,"./p5.Shader":342,"core-js/modules/es.array.iterator":165,"core-js/modules/es.object.get-own-property-descriptor":186,"core-js/modules/es.object.to-string":190,"core-js/modules/es.regexp.exec":195,"core-js/modules/es.string.iterator":200,"core-js/modules/es.string.split":206,"core-js/modules/es.string.sub":208,"core-js/modules/es.symbol":212,"core-js/modules/es.symbol.description":210,"core-js/modules/es.symbol.iterator":211,"core-js/modules/es.weak-map":244,"core-js/modules/web.dom-collections.iterator":246}]},{},[267])(267)})})(Th);var T1=Th.exports;const Xc=E1(T1),k1=Sn(()=>({provide:{p5:Xc,p5:Xc}})),M1=[y0,v0,Lb,Db,Fb,w1,x1,S1,k1],C1=gr({props:{vnode:{type:Object,required:!0},route:{type:Object,required:!0},vnodeRef:Object,renderKey:String,trackRootNodes:Boolean},setup(r){const i=r.renderKey,w=r.route,t={};for(const x in r.route)Object.defineProperty(t,x,{get:()=>i===r.renderKey?r.route[x]:w[x]});return qr(xs,ps(t)),()=>or(r.vnode,{ref:r.vnodeRef})}}),O1=gr({name:"NuxtPage",inheritAttrs:!1,props:{name:{type:String},transition:{type:[Boolean,Object],default:void 0},keepalive:{type:[Boolean,Object],default:void 0},route:{type:Object},pageKey:{type:[Function,String],default:null}},setup(r,{attrs:i,expose:w}){const t=Dt(),x=mt(),v=zt(xs,null);let s;w({pageRef:x});const u=zt(Wf,null);let o;const f=t.deferHydration();if(t.isHydrating){const g=t.hooks.hookOnce("app:error",f);Xr().beforeEach(g)}return r.pageKey&&Bn(()=>r.pageKey,(g,m)=>{g!==m&&t.callHook("page:loading:start")}),()=>or(Sh,{name:r.name,route:r.route,...i},{default:g=>{const m=A1(v,g.route,g.Component),n=v&&v.matched.length===g.route.matched.length;if(!g.Component){if(o&&!n)return o;f();return}if(o&&u&&!u.isCurrent(g.route))return o;if(m&&v&&(!u||u!=null&&u.isCurrent(v)))return n?o:null;const a=Qa(g,r.pageKey);!t.isHydrating&&!R1(v,g.route,g.Component)&&s===a&&t.callHook("page:loading:end"),s=a;const l=!!(r.transition??g.route.meta.pageTransition??Ya),d=l&&P1([r.transition,g.route.meta.pageTransition,Ya,{onAfterLeave:()=>{t.callHook("page:transition:finish",g.Component)}}].filter(Boolean)),y=r.keepalive??g.route.meta.keepalive??a0;return o=Eh(El,l&&d,jb(y,or(jl,{suspensible:!0,onPending:()=>t.callHook("page:start",g.Component),onResolve:()=>{Hr(()=>t.callHook("page:finish",g.Component).then(()=>t.callHook("page:loading:end")).finally(f))}},{default:()=>{const h=or(C1,{key:a||void 0,vnode:g.Component,route:g.route,renderKey:a||void 0,trackRootNodes:l,vnodeRef:x});return y&&(h.type.name=g.Component.type.name||g.Component.type.__name||"RouteProvider"),h}}))).default(),o}})}});function P1(r){const i=r.map(w=>({...w,onAfterLeave:w.onAfterLeave?Il(w.onAfterLeave):void 0}));return Hf(...i)}function A1(r,i,w){if(!r)return!1;const t=i.matched.findIndex(x=>{var v;return((v=x.components)==null?void 0:v.default)===(w==null?void 0:w.type)});return!t||t===-1?!1:i.matched.slice(0,t).some((x,v)=>{var s,u,o;return((s=x.components)==null?void 0:s.default)!==((o=(u=r.matched[v])==null?void 0:u.components)==null?void 0:o.default)})||w&&Qa({route:i,Component:w})!==Qa({route:r,Component:w})}function R1(r,i,w){return r?i.matched.findIndex(x=>{var v;return((v=x.components)==null?void 0:v.default)===(w==null?void 0:w.type)})t.default||t);return()=>or(w,r.layoutProps,i.slots)}}),I1=gr({name:"NuxtLayout",inheritAttrs:!1,props:{name:{type:[String,Boolean,Object],default:null},fallback:{type:[String,Object],default:null}},setup(r,i){const w=Dt(),t=zt(xs),x=t===Ti()?wb():t,v=jt(()=>{let o=Vt(r.name)??x.meta.layout??"default";return o&&!(o in Fn)&&r.fallback&&(o=Vt(r.fallback)),o}),s=mt();i.expose({layoutRef:s});const u=w.deferHydration();if(w.isHydrating){const o=w.hooks.hookOnce("app:error",u);Xr().beforeEach(o)}return()=>{const o=v.value&&v.value in Fn,f=x.meta.layoutTransition??i0;return Eh(El,o&&f,{default:()=>or(jl,{suspensible:!0,onResolve:()=>{Hr(u)}},{default:()=>or(D1,{layoutProps:_f(i.attrs,{ref:s}),key:v.value||void 0,name:v.value,shouldProvide:!r.name,hasTransition:!!f},i.slots)})}).default()}}}),D1=gr({name:"NuxtLayoutProvider",inheritAttrs:!1,props:{name:{type:[String,Boolean]},layoutProps:{type:Object},hasTransition:{type:Boolean},shouldProvide:{type:Boolean}},setup(r,i){const w=r.name;return r.shouldProvide&&qr(Wf,{isCurrent:t=>w===(t.meta.layout??"default")}),()=>{var t,x;return!w||typeof w=="string"&&!(w in Fn)?(x=(t=i.slots).default)==null?void 0:x.call(t):or(L1,{key:w,layoutProps:r.layoutProps,name:w},i.slots)}}}),F1={class:"bg-background"},N1=gr({__name:"app",setup(r){return n0({title:"Colton Padden",ogTitle:"Colton Padden",description:"This is where you can find the blog, portfolio, and experiments of Colton Padden.",ogDescription:"This is where you can find the blog, portfolio, and experiments of Colton Padden."}),(i,w)=>{const t=O1,x=I1;return jr(),bs("body",F1,[ft(x,null,{default:Ur(()=>[ft(t)]),_:1})])}}}),kh=(r,i)=>{const w=r.__vccOpts||r;for(const[t,x]of i)w[t]=x;return w},U1={},B1={width:"366",height:"24",viewBox:"0 0 366 24",fill:"none",xmlns:"http://www.w3.org/2000/svg"};function G1(r,i){return jr(),bs("svg",B1,i[0]||(i[0]=[ry('',6)]))}const V1=kh(U1,[["render",G1]]);async function Mh(r,i=Xr()){const{path:w,matched:t}=i.resolve(r);if(!t.length||(i._routePreloaded||(i._routePreloaded=new Set),i._routePreloaded.has(w)))return;const x=i._preloadPromises=i._preloadPromises||[];if(x.length>4)return Promise.all(x).then(()=>Mh(r,i));i._routePreloaded.add(w);const v=t.map(s=>{var u;return(u=s.components)==null?void 0:u.default}).filter(s=>typeof s=="function");for(const s of v){const u=Promise.resolve(s()).catch(()=>{}).finally(()=>x.splice(x.indexOf(u)));x.push(u)}await Promise.all(x)}const H1=(...r)=>r.find(i=>i!==void 0);function z1(r){const i=r.componentName||"NuxtLink";function w(t,x){if(!t||r.trailingSlash!=="append"&&r.trailingSlash!=="remove")return t;if(typeof t=="string")return Yc(t,r.trailingSlash);const v="path"in t&&t.path!==void 0?t.path:x(t).path;return{...t,name:void 0,path:Yc(v,r.trailingSlash)}}return gr({name:i,props:{to:{type:[String,Object],default:void 0,required:!1},href:{type:[String,Object],default:void 0,required:!1},target:{type:String,default:void 0,required:!1},rel:{type:String,default:void 0,required:!1},noRel:{type:Boolean,default:void 0,required:!1},prefetch:{type:Boolean,default:void 0,required:!1},noPrefetch:{type:Boolean,default:void 0,required:!1},activeClass:{type:String,default:void 0,required:!1},exactActiveClass:{type:String,default:void 0,required:!1},prefetchedClass:{type:String,default:void 0,required:!1},replace:{type:Boolean,default:void 0,required:!1},ariaCurrentValue:{type:String,default:void 0,required:!1},external:{type:Boolean,default:void 0,required:!1},custom:{type:Boolean,default:void 0,required:!1}},setup(t,{slots:x}){const v=Xr(),s=Ei(),u=jt(()=>{const l=t.to||t.href||"";return w(l,v.resolve)}),o=jt(()=>typeof u.value=="string"&&jn(u.value,{acceptRelative:!0})),f=jt(()=>t.target&&t.target!=="_self"),g=jt(()=>t.external||f.value?!0:typeof u.value=="object"?!1:u.value===""||o.value),m=mt(!1),n=mt(null),a=l=>{var d;n.value=t.custom?(d=l==null?void 0:l.$el)==null?void 0:d.nextElementSibling:l==null?void 0:l.$el};if(t.prefetch!==!1&&t.noPrefetch!==!0&&t.target!=="_blank"&&!X1()){const d=Dt();let y,h=null;en(()=>{const c=q1();Dl(()=>{y=Ja(()=>{var p;(p=n==null?void 0:n.value)!=null&&p.tagName&&(h=c.observe(n.value,async()=>{h==null||h(),h=null;const b=typeof u.value=="string"?u.value:v.resolve(u.value).fullPath;await Promise.all([d.hooks.callHook("link:prefetch",b).catch(()=>{}),!g.value&&Mh(u.value,v).catch(()=>{})]),m.value=!0}))})})}),gs(()=>{y&&Ib(y),h==null||h(),h=null})}return()=>{var h,c;if(!g.value){const p={ref:a,to:u.value,activeClass:t.activeClass||r.activeClass,exactActiveClass:t.exactActiveClass||r.exactActiveClass,replace:t.replace,ariaCurrentValue:t.ariaCurrentValue,custom:t.custom};return t.custom||(m.value&&(p.class=t.prefetchedClass||r.prefetchedClass),p.rel=t.rel||void 0),or(bm("RouterLink"),p,x.default)}const l=typeof u.value=="object"?((h=v.resolve(u.value))==null?void 0:h.href)??null:u.value&&!t.external&&!o.value?w(Si(s.app.baseURL,u.value),v.resolve):u.value||null,d=t.target||null,y=H1(t.noRel?"":t.rel,r.externalRelAttribute,o.value||f.value?"noopener noreferrer":"")||null;if(t.custom){if(!x.default)return null;const p=()=>sv(l,{replace:t.replace,external:t.external});return x.default({href:l,navigate:p,get route(){if(!l)return;const b=ws(l);return{path:b.pathname,fullPath:b.pathname,get query(){return Of(b.search)},hash:b.hash,params:{},name:void 0,matched:[],redirectedFrom:void 0,meta:{},href:l}},rel:y,target:d,isExternal:g.value,isActive:!1,isExactActive:!1})}return or("a",{ref:n,href:l,rel:y,target:d},(c=x.default)==null?void 0:c.call(x))}}})}const W1=z1(l0);function Yc(r,i){const w=i==="append"?ai:ji;return jn(r)&&!r.startsWith("http")?r:w(r,!0)}function q1(){const r=Dt();if(r._observer)return r._observer;let i=null;const w=new Map,t=(v,s)=>(i||(i=new IntersectionObserver(u=>{for(const o of u){const f=w.get(o.target);(o.isIntersecting||o.intersectionRatio>0)&&f&&f()}})),w.set(v,s),i.observe(v),()=>{w.delete(v),i.unobserve(v),w.size===0&&(i.disconnect(),i=null)});return r._observer={observe:t}}function X1(){const r=navigator.connection;return!!(r&&(r.saveData||/2g/.test(r.effectiveType)))}var $c;let Y1=Symbol("headlessui.useid"),$1=0;const Pi=($c=sm)!=null?$c:function(){return zt(Y1,()=>`${++$1}`)()};function Nt(r){var i;if(r==null||r.value==null)return null;let w=(i=r.value.$el)!=null?i:r.value;return w instanceof Node?w:null}function so(r,i,...w){if(r in i){let x=i[r];return typeof x=="function"?x(...w):x}let t=new Error(`Tried to handle "${r}" but there is no handler defined. Only defined handlers are: ${Object.keys(i).map(x=>`"${x}"`).join(", ")}.`);throw Error.captureStackTrace&&Error.captureStackTrace(t,so),t}var Z1=Object.defineProperty,K1=(r,i,w)=>i in r?Z1(r,i,{enumerable:!0,configurable:!0,writable:!0,value:w}):r[i]=w,Zc=(r,i,w)=>(K1(r,typeof i!="symbol"?i+"":i,w),w);let Q1=class{constructor(){Zc(this,"current",this.detect()),Zc(this,"currentId",0)}set(i){this.current!==i&&(this.currentId=0,this.current=i)}reset(){this.set(this.detect())}nextId(){return++this.currentId}get isServer(){return this.current==="server"}get isClient(){return this.current==="client"}detect(){return typeof window>"u"||typeof document>"u"?"server":"client"}},Ai=new Q1;function Fl(r){if(Ai.isServer)return null;if(r instanceof Node)return r.ownerDocument;if(r!=null&&r.hasOwnProperty("value")){let i=Nt(r);if(i)return i.ownerDocument}return document}let el=["[contentEditable=true]","[tabindex]","a[href]","area[href]","button:not([disabled])","iframe","input:not([disabled])","select:not([disabled])","textarea:not([disabled])"].map(r=>`${r}:not([tabindex='-1'])`).join(",");var tl=(r=>(r[r.First=1]="First",r[r.Previous=2]="Previous",r[r.Next=4]="Next",r[r.Last=8]="Last",r[r.WrapAround=16]="WrapAround",r[r.NoScroll=32]="NoScroll",r))(tl||{}),J1=(r=>(r[r.Error=0]="Error",r[r.Overflow=1]="Overflow",r[r.Success=2]="Success",r[r.Underflow=3]="Underflow",r))(J1||{}),e_=(r=>(r[r.Previous=-1]="Previous",r[r.Next=1]="Next",r))(e_||{});function Ch(r=document.body){return r==null?[]:Array.from(r.querySelectorAll(el)).sort((i,w)=>Math.sign((i.tabIndex||Number.MAX_SAFE_INTEGER)-(w.tabIndex||Number.MAX_SAFE_INTEGER)))}var Nl=(r=>(r[r.Strict=0]="Strict",r[r.Loose=1]="Loose",r))(Nl||{});function Ul(r,i=0){var w;return r===((w=Fl(r))==null?void 0:w.body)?!1:so(i,{0(){return r.matches(el)},1(){let t=r;for(;t!==null;){if(t.matches(el))return!0;t=t.parentElement}return!1}})}function Oh(r){let i=Fl(r);Hr(()=>{i&&!Ul(i.activeElement,0)&&r_(r)})}var t_=(r=>(r[r.Keyboard=0]="Keyboard",r[r.Mouse=1]="Mouse",r))(t_||{});typeof window<"u"&&typeof document<"u"&&(document.addEventListener("keydown",r=>{r.metaKey||r.altKey||r.ctrlKey||(document.documentElement.dataset.headlessuiFocusVisible="")},!0),document.addEventListener("click",r=>{r.detail===1?delete document.documentElement.dataset.headlessuiFocusVisible:r.detail===0&&(document.documentElement.dataset.headlessuiFocusVisible="")},!0));function r_(r){r==null||r.focus({preventScroll:!0})}let n_=["textarea","input"].join(",");function o_(r){var i,w;return(w=(i=r==null?void 0:r.matches)==null?void 0:i.call(r,n_))!=null?w:!1}function Ph(r,i=w=>w){return r.slice().sort((w,t)=>{let x=i(w),v=i(t);if(x===null||v===null)return 0;let s=x.compareDocumentPosition(v);return s&Node.DOCUMENT_POSITION_FOLLOWING?-1:s&Node.DOCUMENT_POSITION_PRECEDING?1:0})}function s_(r,i){return i_(Ch(),i,{relativeTo:r})}function i_(r,i,{sorted:w=!0,relativeTo:t=null,skipElements:x=[]}={}){var v;let s=(v=Array.isArray(r)?r.length>0?r[0].ownerDocument:document:r==null?void 0:r.ownerDocument)!=null?v:document,u=Array.isArray(r)?w?Ph(r):r:Ch(r);x.length>0&&u.length>1&&(u=u.filter(l=>!x.includes(l))),t=t??s.activeElement;let o=(()=>{if(i&5)return 1;if(i&10)return-1;throw new Error("Missing Focus.First, Focus.Previous, Focus.Next or Focus.Last")})(),f=(()=>{if(i&1)return 0;if(i&2)return Math.max(0,u.indexOf(t))-1;if(i&4)return Math.max(0,u.indexOf(t))+1;if(i&8)return u.length-1;throw new Error("Missing Focus.First, Focus.Previous, Focus.Next or Focus.Last")})(),g=i&32?{preventScroll:!0}:{},m=0,n=u.length,a;do{if(m>=n||m+n<=0)return 0;let l=f+m;if(i&16)l=(l+n)%n;else{if(l<0)return 3;if(l>=n)return 1}a=u[l],a==null||a.focus(g),m+=o}while(a!==s.activeElement);return i&6&&o_(a)&&a.select(),2}function a_(){return/iPhone/gi.test(window.navigator.platform)||/Mac/gi.test(window.navigator.platform)&&window.navigator.maxTouchPoints>0}function l_(){return/Android/gi.test(window.navigator.userAgent)}function u_(){return a_()||l_()}function zs(r,i,w){Ai.isServer||fn(t=>{document.addEventListener(r,i,w),t(()=>document.removeEventListener(r,i,w))})}function c_(r,i,w){Ai.isServer||fn(t=>{window.addEventListener(r,i,w),t(()=>window.removeEventListener(r,i,w))})}function d_(r,i,w=jt(()=>!0)){function t(v,s){if(!w.value||v.defaultPrevented)return;let u=s(v);if(u===null||!u.getRootNode().contains(u))return;let o=function f(g){return typeof g=="function"?f(g()):Array.isArray(g)||g instanceof Set?g:[g]}(r);for(let f of o){if(f===null)continue;let g=f instanceof HTMLElement?f:Nt(f);if(g!=null&&g.contains(u)||v.composed&&v.composedPath().includes(g))return}return!Ul(u,Nl.Loose)&&u.tabIndex!==-1&&v.preventDefault(),i(v,u)}let x=mt(null);zs("pointerdown",v=>{var s,u;w.value&&(x.value=((u=(s=v.composedPath)==null?void 0:s.call(v))==null?void 0:u[0])||v.target)},!0),zs("mousedown",v=>{var s,u;w.value&&(x.value=((u=(s=v.composedPath)==null?void 0:s.call(v))==null?void 0:u[0])||v.target)},!0),zs("click",v=>{u_()||x.value&&(t(v,()=>x.value),x.value=null)},!0),zs("touchend",v=>t(v,()=>v.target instanceof HTMLElement?v.target:null),!0),c_("blur",v=>t(v,()=>window.document.activeElement instanceof HTMLIFrameElement?window.document.activeElement:null),!0)}function Kc(r,i){if(r)return r;let w=i??"button";if(typeof w=="string"&&w.toLowerCase()==="button")return"button"}function f_(r,i){let w=mt(Kc(r.value.type,r.value.as));return en(()=>{w.value=Kc(r.value.type,r.value.as)}),fn(()=>{var t;w.value||Nt(i)&&Nt(i)instanceof HTMLButtonElement&&!((t=Nt(i))!=null&&t.hasAttribute("type"))&&(w.value="button")}),w}let Qc=/([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g;function Jc(r){var i,w;let t=(i=r.innerText)!=null?i:"",x=r.cloneNode(!0);if(!(x instanceof HTMLElement))return t;let v=!1;for(let u of x.querySelectorAll('[hidden],[aria-hidden],[role="img"]'))u.remove(),v=!0;let s=v?(w=x.innerText)!=null?w:"":t;return Qc.test(s)&&(s=s.replace(Qc,"")),s}function h_(r){let i=r.getAttribute("aria-label");if(typeof i=="string")return i.trim();let w=r.getAttribute("aria-labelledby");if(w){let t=w.split(" ").map(x=>{let v=document.getElementById(x);if(v){let s=v.getAttribute("aria-label");return typeof s=="string"?s.trim():Jc(v).trim()}return null}).filter(Boolean);if(t.length>0)return t.join(", ")}return Jc(r).trim()}function p_(r){let i=mt(""),w=mt("");return()=>{let t=Nt(r);if(!t)return"";let x=t.innerText;if(i.value===x)return w.value;let v=h_(t).trim().toLowerCase();return i.value=x,w.value=v,v}}function ed(r){return[r.screenX,r.screenY]}function m_(){let r=mt([-1,-1]);return{wasMoved(i){let w=ed(i);return r.value[0]===w[0]&&r.value[1]===w[1]?!1:(r.value=w,!0)},update(i){r.value=ed(i)}}}function y_({container:r,accept:i,walk:w,enabled:t}){fn(()=>{let x=r.value;if(!x||t!==void 0&&!t.value)return;let v=Fl(r);if(!v)return;let s=Object.assign(o=>i(o),{acceptNode:i}),u=v.createTreeWalker(x,NodeFilter.SHOW_ELEMENT,s,!1);for(;u.nextNode();)w(u.currentNode)})}let Ah=Symbol("Context");var Gr=(r=>(r[r.Open=1]="Open",r[r.Closed=2]="Closed",r[r.Closing=4]="Closing",r[r.Opening=8]="Opening",r))(Gr||{});function g_(){return Bl()!==null}function Bl(){return zt(Ah,null)}function Rh(r){qr(Ah,r)}var ur=(r=>(r.Space=" ",r.Enter="Enter",r.Escape="Escape",r.Backspace="Backspace",r.Delete="Delete",r.ArrowLeft="ArrowLeft",r.ArrowUp="ArrowUp",r.ArrowRight="ArrowRight",r.ArrowDown="ArrowDown",r.Home="Home",r.End="End",r.PageUp="PageUp",r.PageDown="PageDown",r.Tab="Tab",r))(ur||{});function v_(r){throw new Error("Unexpected object: "+r)}var Vr=(r=>(r[r.First=0]="First",r[r.Previous=1]="Previous",r[r.Next=2]="Next",r[r.Last=3]="Last",r[r.Specific=4]="Specific",r[r.Nothing=5]="Nothing",r))(Vr||{});function b_(r,i){let w=i.resolveItems();if(w.length<=0)return null;let t=i.resolveActiveIndex(),x=t??-1;switch(r.focus){case 0:{for(let v=0;v=0;--v)if(!i.resolveDisabled(w[v],v,w))return v;return t}case 2:{for(let v=x+1;v=0;--v)if(!i.resolveDisabled(w[v],v,w))return v;return t}case 4:{for(let v=0;v(r[r.None=0]="None",r[r.RenderStrategy=1]="RenderStrategy",r[r.Static=2]="Static",r))(hi||{}),Nn=(r=>(r[r.Unmount=0]="Unmount",r[r.Hidden=1]="Hidden",r))(Nn||{});function Ao({visible:r=!0,features:i=0,ourProps:w,theirProps:t,...x}){var v;let s=Ih(t,w),u=Object.assign(x,{props:s});if(r||i&2&&s.static)return ga(u);if(i&1){let o=(v=s.unmount)==null||v?0:1;return so(o,{0(){return null},1(){return ga({...x,props:{...s,hidden:!0,style:{display:"none"}}})}})}return ga(u)}function ga({props:r,attrs:i,slots:w,slot:t,name:x}){var v,s;let{as:u,...o}=Dh(r,["unmount","static"]),f=(v=w.default)==null?void 0:v.call(w,t),g={};if(t){let m=!1,n=[];for(let[a,l]of Object.entries(t))typeof l=="boolean"&&(m=!0),l===!0&&n.push(a);m&&(g["data-headlessui-state"]=n.join(" "))}if(u==="template"){if(f=Lh(f??[]),Object.keys(o).length>0||Object.keys(i).length>0){let[m,...n]=f??[];if(!__(m)||n.length>0)throw new Error(['Passing props on "template"!',"",`The current component <${x} /> is rendering a "template".`,"However we need to passthrough the following props:",Object.keys(o).concat(Object.keys(i)).map(d=>d.trim()).filter((d,y,h)=>h.indexOf(d)===y).sort((d,y)=>d.localeCompare(y)).map(d=>` - ${d}`).join(` -`),"","You can apply a few solutions:",['Add an `as="..."` prop, to ensure that we render an actual element instead of a "template".',"Render a single element as the child so that we can forward the props onto that element."].map(d=>` - ${d}`).join(` -`)].join(` -`));let a=Ih((s=m.props)!=null?s:{},o,g),l=hn(m,a,!0);for(let d in a)d.startsWith("on")&&(l.props||(l.props={}),l.props[d]=a[d]);return l}return Array.isArray(f)&&f.length===1?f[0]:f}return or(u,Object.assign({},o,g),{default:()=>f})}function Lh(r){return r.flatMap(i=>i.type===mr?Lh(i.children):[i])}function Ih(...r){if(r.length===0)return{};if(r.length===1)return r[0];let i={},w={};for(let t of r)for(let x in t)x.startsWith("on")&&typeof t[x]=="function"?(w[x]!=null||(w[x]=[]),w[x].push(t[x])):i[x]=t[x];if(i.disabled||i["aria-disabled"])return Object.assign(i,Object.fromEntries(Object.keys(w).map(t=>[t,void 0])));for(let t in w)Object.assign(i,{[t](x,...v){let s=w[t];for(let u of s){if(x instanceof Event&&x.defaultPrevented)return;u(x,...v)}}});return i}function Dh(r,i=[]){let w=Object.assign({},r);for(let t of i)t in w&&delete w[t];return w}function __(r){return r==null?!1:typeof r.type=="string"||typeof r.type=="object"||typeof r.type=="function"}var w_=(r=>(r[r.Open=0]="Open",r[r.Closed=1]="Closed",r))(w_||{}),x_=(r=>(r[r.Pointer=0]="Pointer",r[r.Other=1]="Other",r))(x_||{});function j_(r){requestAnimationFrame(()=>requestAnimationFrame(r))}let Fh=Symbol("MenuContext");function Ri(r){let i=zt(Fh,null);if(i===null){let w=new Error(`<${r} /> is missing a parent component.`);throw Error.captureStackTrace&&Error.captureStackTrace(w,Ri),w}return i}let S_=gr({name:"Menu",props:{as:{type:[Object,String],default:"template"}},setup(r,{slots:i,attrs:w}){let t=mt(1),x=mt(null),v=mt(null),s=mt([]),u=mt(""),o=mt(null),f=mt(1);function g(n=a=>a){let a=o.value!==null?s.value[o.value]:null,l=Ph(n(s.value.slice()),y=>Nt(y.dataRef.domRef)),d=a?l.indexOf(a):null;return d===-1&&(d=null),{items:l,activeItemIndex:d}}let m={menuState:t,buttonRef:x,itemsRef:v,items:s,searchQuery:u,activeItemIndex:o,activationTrigger:f,closeMenu:()=>{t.value=1,o.value=null},openMenu:()=>t.value=0,goToItem(n,a,l){let d=g(),y=b_(n===Vr.Specific?{focus:Vr.Specific,id:a}:{focus:n},{resolveItems:()=>d.items,resolveActiveIndex:()=>d.activeItemIndex,resolveId:h=>h.id,resolveDisabled:h=>h.dataRef.disabled});u.value="",o.value=y,f.value=l??1,s.value=d.items},search(n){let a=u.value!==""?0:1;u.value+=n.toLowerCase();let l=(o.value!==null?s.value.slice(o.value+a).concat(s.value.slice(0,o.value+a)):s.value).find(y=>y.dataRef.textValue.startsWith(u.value)&&!y.dataRef.disabled),d=l?s.value.indexOf(l):-1;d===-1||d===o.value||(o.value=d,f.value=1)},clearSearch(){u.value=""},registerItem(n,a){let l=g(d=>[...d,{id:n,dataRef:a}]);s.value=l.items,o.value=l.activeItemIndex,f.value=1},unregisterItem(n){let a=g(l=>{let d=l.findIndex(y=>y.id===n);return d!==-1&&l.splice(d,1),l});s.value=a.items,o.value=a.activeItemIndex,f.value=1}};return d_([x,v],(n,a)=>{var l;m.closeMenu(),Ul(a,Nl.Loose)||(n.preventDefault(),(l=Nt(x))==null||l.focus())},jt(()=>t.value===0)),qr(Fh,m),Rh(jt(()=>so(t.value,{0:Gr.Open,1:Gr.Closed}))),()=>{let n={open:t.value===0,close:m.closeMenu};return Ao({ourProps:{},theirProps:r,slot:n,slots:i,attrs:w,name:"Menu"})}}}),E_=gr({name:"MenuButton",props:{disabled:{type:Boolean,default:!1},as:{type:[Object,String],default:"button"},id:{type:String,default:null}},setup(r,{attrs:i,slots:w,expose:t}){var x;let v=(x=r.id)!=null?x:`headlessui-menu-button-${Pi()}`,s=Ri("MenuButton");t({el:s.buttonRef,$el:s.buttonRef});function u(m){switch(m.key){case ur.Space:case ur.Enter:case ur.ArrowDown:m.preventDefault(),m.stopPropagation(),s.openMenu(),Hr(()=>{var n;(n=Nt(s.itemsRef))==null||n.focus({preventScroll:!0}),s.goToItem(Vr.First)});break;case ur.ArrowUp:m.preventDefault(),m.stopPropagation(),s.openMenu(),Hr(()=>{var n;(n=Nt(s.itemsRef))==null||n.focus({preventScroll:!0}),s.goToItem(Vr.Last)});break}}function o(m){switch(m.key){case ur.Space:m.preventDefault();break}}function f(m){r.disabled||(s.menuState.value===0?(s.closeMenu(),Hr(()=>{var n;return(n=Nt(s.buttonRef))==null?void 0:n.focus({preventScroll:!0})})):(m.preventDefault(),s.openMenu(),j_(()=>{var n;return(n=Nt(s.itemsRef))==null?void 0:n.focus({preventScroll:!0})})))}let g=f_(jt(()=>({as:r.as,type:i.type})),s.buttonRef);return()=>{var m;let n={open:s.menuState.value===0},{...a}=r,l={ref:s.buttonRef,id:v,type:g.value,"aria-haspopup":"menu","aria-controls":(m=Nt(s.itemsRef))==null?void 0:m.id,"aria-expanded":s.menuState.value===0,onKeydown:u,onKeyup:o,onClick:f};return Ao({ourProps:l,theirProps:a,slot:n,attrs:i,slots:w,name:"MenuButton"})}}}),T_=gr({name:"MenuItems",props:{as:{type:[Object,String],default:"div"},static:{type:Boolean,default:!1},unmount:{type:Boolean,default:!0},id:{type:String,default:null}},setup(r,{attrs:i,slots:w,expose:t}){var x;let v=(x=r.id)!=null?x:`headlessui-menu-items-${Pi()}`,s=Ri("MenuItems"),u=mt(null);t({el:s.itemsRef,$el:s.itemsRef}),y_({container:jt(()=>Nt(s.itemsRef)),enabled:jt(()=>s.menuState.value===0),accept(n){return n.getAttribute("role")==="menuitem"?NodeFilter.FILTER_REJECT:n.hasAttribute("role")?NodeFilter.FILTER_SKIP:NodeFilter.FILTER_ACCEPT},walk(n){n.setAttribute("role","none")}});function o(n){var a;switch(u.value&&clearTimeout(u.value),n.key){case ur.Space:if(s.searchQuery.value!=="")return n.preventDefault(),n.stopPropagation(),s.search(n.key);case ur.Enter:if(n.preventDefault(),n.stopPropagation(),s.activeItemIndex.value!==null){let l=s.items.value[s.activeItemIndex.value];(a=Nt(l.dataRef.domRef))==null||a.click()}s.closeMenu(),Oh(Nt(s.buttonRef));break;case ur.ArrowDown:return n.preventDefault(),n.stopPropagation(),s.goToItem(Vr.Next);case ur.ArrowUp:return n.preventDefault(),n.stopPropagation(),s.goToItem(Vr.Previous);case ur.Home:case ur.PageUp:return n.preventDefault(),n.stopPropagation(),s.goToItem(Vr.First);case ur.End:case ur.PageDown:return n.preventDefault(),n.stopPropagation(),s.goToItem(Vr.Last);case ur.Escape:n.preventDefault(),n.stopPropagation(),s.closeMenu(),Hr(()=>{var l;return(l=Nt(s.buttonRef))==null?void 0:l.focus({preventScroll:!0})});break;case ur.Tab:n.preventDefault(),n.stopPropagation(),s.closeMenu(),Hr(()=>s_(Nt(s.buttonRef),n.shiftKey?tl.Previous:tl.Next));break;default:n.key.length===1&&(s.search(n.key),u.value=setTimeout(()=>s.clearSearch(),350));break}}function f(n){switch(n.key){case ur.Space:n.preventDefault();break}}let g=Bl(),m=jt(()=>g!==null?(g.value&Gr.Open)===Gr.Open:s.menuState.value===0);return()=>{var n,a;let l={open:s.menuState.value===0},{...d}=r,y={"aria-activedescendant":s.activeItemIndex.value===null||(n=s.items.value[s.activeItemIndex.value])==null?void 0:n.id,"aria-labelledby":(a=Nt(s.buttonRef))==null?void 0:a.id,id:v,onKeydown:o,onKeyup:f,role:"menu",tabIndex:0,ref:s.itemsRef};return Ao({ourProps:y,theirProps:d,slot:l,attrs:i,slots:w,features:hi.RenderStrategy|hi.Static,visible:m.value,name:"MenuItems"})}}}),k_=gr({name:"MenuItem",inheritAttrs:!1,props:{as:{type:[Object,String],default:"template"},disabled:{type:Boolean,default:!1},id:{type:String,default:null}},setup(r,{slots:i,attrs:w,expose:t}){var x;let v=(x=r.id)!=null?x:`headlessui-menu-item-${Pi()}`,s=Ri("MenuItem"),u=mt(null);t({el:u,$el:u});let o=jt(()=>s.activeItemIndex.value!==null?s.items.value[s.activeItemIndex.value].id===v:!1),f=p_(u),g=jt(()=>({disabled:r.disabled,get textValue(){return f()},domRef:u}));en(()=>s.registerItem(v,g)),vs(()=>s.unregisterItem(v)),fn(()=>{s.menuState.value===0&&o.value&&s.activationTrigger.value!==0&&Hr(()=>{var h,c;return(c=(h=Nt(u))==null?void 0:h.scrollIntoView)==null?void 0:c.call(h,{block:"nearest"})})});function m(h){if(r.disabled)return h.preventDefault();s.closeMenu(),Oh(Nt(s.buttonRef))}function n(){if(r.disabled)return s.goToItem(Vr.Nothing);s.goToItem(Vr.Specific,v)}let a=m_();function l(h){a.update(h)}function d(h){a.wasMoved(h)&&(r.disabled||o.value||s.goToItem(Vr.Specific,v,0))}function y(h){a.wasMoved(h)&&(r.disabled||o.value&&s.goToItem(Vr.Nothing))}return()=>{let{disabled:h,...c}=r,p={active:o.value,disabled:h,close:s.closeMenu};return Ao({ourProps:{id:v,ref:u,role:"menuitem",tabIndex:h===!0?void 0:-1,"aria-disabled":h===!0?!0:void 0,onClick:m,onFocus:n,onPointerenter:l,onMouseenter:l,onPointermove:d,onMousemove:d,onPointerleave:y,onMouseleave:y},theirProps:{...w,...c},slot:p,attrs:w,slots:i,name:"MenuItem"})}}});function M_(r,i){return jr(),bs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true","data-slot":"icon"},[Pt("path",{"fill-rule":"evenodd",d:"M2 4.75A.75.75 0 0 1 2.75 4h14.5a.75.75 0 0 1 0 1.5H2.75A.75.75 0 0 1 2 4.75ZM2 10a.75.75 0 0 1 .75-.75h14.5a.75.75 0 0 1 0 1.5H2.75A.75.75 0 0 1 2 10Zm0 5.25a.75.75 0 0 1 .75-.75h14.5a.75.75 0 0 1 0 1.5H2.75a.75.75 0 0 1-.75-.75Z","clip-rule":"evenodd"})])}const C_={class:"container mx-auto py-6"},O_={class:"flex items-center text-gray-200"},P_={class:"flex items-center"},A_={class:"px-1 py-1"},R_={href:"/articles"},L_={href:"/talks"},I_={href:"/playground"},D_={__name:"Header",setup(r){return Ti(),(i,w)=>{const t=V1,x=W1,v=E_,s=k_,u=T_,o=S_;return jr(),bs("nav",C_,[Pt("div",O_,[ft(x,{to:"/",class:"flex-1"},{default:Ur(()=>[ft(t,{class:"text-white hover:text-orange-500 w-32 md:w-64"})]),_:1}),Pt("div",P_,[ft(x,{to:"https://github.com/cmpadden"},{default:Ur(()=>w[0]||(w[0]=[Pt("svg",{class:"mr-2 inline h-6 w-6 hover:text-orange-300",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor"},[Pt("path",{d:"M12.001 2C6.47598 2 2.00098 6.475 2.00098 12C2.00098 16.425 4.86348 20.1625 8.83848 21.4875C9.33848 21.575 9.52598 21.275 9.52598 21.0125C9.52598 20.775 9.51348 19.9875 9.51348 19.15C7.00098 19.6125 6.35098 18.5375 6.15098 17.975C6.03848 17.6875 5.55098 16.8 5.12598 16.5625C4.77598 16.375 4.27598 15.9125 5.11348 15.9C5.90098 15.8875 6.46348 16.625 6.65098 16.925C7.55098 18.4375 8.98848 18.0125 9.56348 17.75C9.65098 17.1 9.91348 16.6625 10.201 16.4125C7.97598 16.1625 5.65098 15.3 5.65098 11.475C5.65098 10.3875 6.03848 9.4875 6.67598 8.7875C6.57598 8.5375 6.22598 7.5125 6.77598 6.1375C6.77598 6.1375 7.61348 5.875 9.52598 7.1625C10.326 6.9375 11.176 6.825 12.026 6.825C12.876 6.825 13.726 6.9375 14.526 7.1625C16.4385 5.8625 17.276 6.1375 17.276 6.1375C17.826 7.5125 17.476 8.5375 17.376 8.7875C18.0135 9.4875 18.401 10.375 18.401 11.475C18.401 15.3125 16.0635 16.1625 13.8385 16.4125C14.201 16.725 14.5135 17.325 14.5135 18.2625C14.5135 19.6 14.501 20.675 14.501 21.0125C14.501 21.275 14.6885 21.5875 15.1885 21.4875C19.259 20.1133 21.9999 16.2963 22.001 12C22.001 6.475 17.526 2 12.001 2Z"})],-1)])),_:1}),ft(o,{as:"div",class:"relative z-50 inline-block text-left"},{default:Ur(()=>[Pt("div",null,[ft(v,{class:"inline-flex w-full justify-center rounded-md bg-black/50 p-2 text-sm font-medium text-white hover:bg-opacity-30 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75"},{default:Ur(()=>[ft(Vt(M_),{class:"h-5 w-5 text-white hover:text-orange-500","aria-hidden":"true"})]),_:1})]),ft(El,{"enter-active-class":"transition duration-100 ease-out","enter-from-class":"transform scale-95 opacity-0","enter-to-class":"transform scale-100 opacity-100","leave-active-class":"transition duration-75 ease-in","leave-from-class":"transform scale-100 opacity-100","leave-to-class":"transform scale-95 opacity-0"},{default:Ur(()=>[ft(u,{class:"absolute right-0 mt-2 w-56 origin-top-right divide-y divide-gray-100 rounded-md bg-black/80 text-white shadow-lg ring-1 ring-black ring-opacity-5 backdrop-blur-sm focus:outline-none"},{default:Ur(()=>[Pt("div",A_,[ft(s,null,{default:Ur(({active:f})=>[Pt("a",R_,[Pt("button",{class:Jn([f?"bg-slate-700 text-white":"text-white","group flex w-full items-center rounded-md px-2 py-2 text-sm"])},w[1]||(w[1]=[Pt("svg",{class:"mr-2 inline h-5 w-5",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor"},[Pt("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10"})],-1),Ko(" Blog ")]),2)])]),_:1}),ft(s,null,{default:Ur(({active:f})=>[Pt("a",L_,[Pt("button",{class:Jn([f?"bg-slate-700":"","group flex w-full items-center rounded-md px-2 py-2 text-sm"])},w[2]||(w[2]=[Pt("svg",{class:"mr-2 inline h-5 w-5",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor"},[Pt("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M3.75 3v11.25A2.25 2.25 0 0 0 6 16.5h2.25M3.75 3h-1.5m1.5 0h16.5m0 0h1.5m-1.5 0v11.25A2.25 2.25 0 0 1 18 16.5h-2.25m-7.5 0h7.5m-7.5 0-1 3m8.5-3 1 3m0 0 .5 1.5m-.5-1.5h-9.5m0 0-.5 1.5M9 11.25v1.5M12 9v3.75m3-6v6"})],-1),Ko(" Talks ")]),2)])]),_:1}),ft(s,null,{default:Ur(({active:f})=>[Pt("a",I_,[Pt("button",{class:Jn([f?"bg-slate-700 text-white":"text-white","group flex w-full items-center rounded-md px-2 py-2 text-sm"])},w[3]||(w[3]=[Pt("svg",{class:"mr-2 inline h-5 w-5",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor"},[Pt("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M9.75 3.104v5.714a2.25 2.25 0 01-.659 1.591L5 14.5M9.75 3.104c-.251.023-.501.05-.75.082m.75-.082a24.301 24.301 0 014.5 0m0 0v5.714c0 .597.237 1.17.659 1.591L19.8 15.3M14.25 3.104c.251.023.501.05.75.082M19.8 15.3l-1.57.393A9.065 9.065 0 0112 15a9.065 9.065 0 00-6.23-.693L5 14.5m14.8.8l1.402 1.402c1.232 1.232.65 3.318-1.067 3.611A48.309 48.309 0 0112 21c-2.773 0-5.491-.235-8.135-.687-1.718-.293-2.3-2.379-1.067-3.61L5 14.5"})],-1),Ko(" Experiments ")]),2)])]),_:1})])]),_:1})]),_:1})]),_:1})])])])}}};function F_(r){typeof queueMicrotask=="function"?queueMicrotask(r):Promise.resolve().then(r).catch(i=>setTimeout(()=>{throw i}))}function Gl(){let r=[],i={addEventListener(w,t,x,v){return w.addEventListener(t,x,v),i.add(()=>w.removeEventListener(t,x,v))},requestAnimationFrame(...w){let t=requestAnimationFrame(...w);i.add(()=>cancelAnimationFrame(t))},nextFrame(...w){i.requestAnimationFrame(()=>{i.requestAnimationFrame(...w)})},setTimeout(...w){let t=setTimeout(...w);i.add(()=>clearTimeout(t))},microTask(...w){let t={current:!0};return F_(()=>{t.current&&w[0]()}),i.add(()=>{t.current=!1})},style(w,t,x){let v=w.style.getPropertyValue(t);return Object.assign(w.style,{[t]:x}),this.add(()=>{Object.assign(w.style,{[t]:v})})},group(w){let t=Gl();return w(t),this.add(()=>t.dispose())},add(w){return r.push(w),()=>{let t=r.indexOf(w);if(t>=0)for(let x of r.splice(t,1))x()}},dispose(){for(let w of r.splice(0))w()}};return i}function N_(r){let i={called:!1};return(...w)=>{if(!i.called)return i.called=!0,r(...w)}}function va(r,...i){r&&i.length>0&&r.classList.add(...i)}function Ws(r,...i){r&&i.length>0&&r.classList.remove(...i)}var rl=(r=>(r.Finished="finished",r.Cancelled="cancelled",r))(rl||{});function U_(r,i){let w=Gl();if(!r)return w.dispose;let{transitionDuration:t,transitionDelay:x}=getComputedStyle(r),[v,s]=[t,x].map(u=>{let[o=0]=u.split(",").filter(Boolean).map(f=>f.includes("ms")?parseFloat(f):parseFloat(f)*1e3).sort((f,g)=>g-f);return o});return v!==0?w.setTimeout(()=>i("finished"),v+s):i("finished"),w.add(()=>i("cancelled")),w.dispose}function td(r,i,w,t,x,v){let s=Gl(),u=v!==void 0?N_(v):()=>{};return Ws(r,...x),va(r,...i,...w),s.nextFrame(()=>{Ws(r,...w),va(r,...t),s.add(U_(r,o=>(Ws(r,...t,...i),va(r,...x),u(o))))}),s.add(()=>Ws(r,...i,...w,...t,...x)),s.add(()=>u("cancelled")),s.dispose}function Zn(r=""){return r.split(/\s+/).filter(i=>i.length>1)}let Vl=Symbol("TransitionContext");var B_=(r=>(r.Visible="visible",r.Hidden="hidden",r))(B_||{});function G_(){return zt(Vl,null)!==null}function V_(){let r=zt(Vl,null);if(r===null)throw new Error("A is used but it is missing a parent .");return r}function H_(){let r=zt(Hl,null);if(r===null)throw new Error("A is used but it is missing a parent .");return r}let Hl=Symbol("NestingContext");function Li(r){return"children"in r?Li(r.children):r.value.filter(({state:i})=>i==="visible").length>0}function Nh(r){let i=mt([]),w=mt(!1);en(()=>w.value=!0),vs(()=>w.value=!1);function t(v,s=Nn.Hidden){let u=i.value.findIndex(({id:o})=>o===v);u!==-1&&(so(s,{[Nn.Unmount](){i.value.splice(u,1)},[Nn.Hidden](){i.value[u].state="hidden"}}),!Li(i)&&w.value&&(r==null||r()))}function x(v){let s=i.value.find(({id:u})=>u===v);return s?s.state!=="visible"&&(s.state="visible"):i.value.push({id:v,state:"visible"}),()=>t(v,Nn.Unmount)}return{children:i,register:x,unregister:t}}let Uh=hi.RenderStrategy,z_=gr({props:{as:{type:[Object,String],default:"div"},show:{type:[Boolean],default:null},unmount:{type:[Boolean],default:!0},appear:{type:[Boolean],default:!1},enter:{type:[String],default:""},enterFrom:{type:[String],default:""},enterTo:{type:[String],default:""},entered:{type:[String],default:""},leave:{type:[String],default:""},leaveFrom:{type:[String],default:""},leaveTo:{type:[String],default:""}},emits:{beforeEnter:()=>!0,afterEnter:()=>!0,beforeLeave:()=>!0,afterLeave:()=>!0},setup(r,{emit:i,attrs:w,slots:t,expose:x}){let v=mt(0);function s(){v.value|=Gr.Opening,i("beforeEnter")}function u(){v.value&=~Gr.Opening,i("afterEnter")}function o(){v.value|=Gr.Closing,i("beforeLeave")}function f(){v.value&=~Gr.Closing,i("afterLeave")}if(!G_()&&g_())return()=>or(Bh,{...r,onBeforeEnter:s,onAfterEnter:u,onBeforeLeave:o,onAfterLeave:f},t);let g=mt(null),m=jt(()=>r.unmount?Nn.Unmount:Nn.Hidden);x({el:g,$el:g});let{show:n,appear:a}=V_(),{register:l,unregister:d}=H_(),y=mt(n.value?"visible":"hidden"),h={value:!0},c=Pi(),p={value:!1},b=Nh(()=>{!p.value&&y.value!=="hidden"&&(y.value="hidden",d(c),f())});en(()=>{let A=l(c);vs(A)}),fn(()=>{if(m.value===Nn.Hidden&&c){if(n.value&&y.value!=="visible"){y.value="visible";return}so(y.value,{hidden:()=>d(c),visible:()=>l(c)})}});let j=Zn(r.enter),M=Zn(r.enterFrom),E=Zn(r.enterTo),k=Zn(r.entered),O=Zn(r.leave),L=Zn(r.leaveFrom),C=Zn(r.leaveTo);en(()=>{fn(()=>{if(y.value==="visible"){let A=Nt(g);if(A instanceof Comment&&A.data==="")throw new Error("Did you forget to passthrough the `ref` to the actual DOM node?")}})});function I(A){let N=h.value&&!a.value,F=Nt(g);!F||!(F instanceof HTMLElement)||N||(p.value=!0,n.value&&s(),n.value||o(),A(n.value?td(F,j,M,E,k,B=>{p.value=!1,B===rl.Finished&&u()}):td(F,O,L,C,k,B=>{p.value=!1,B===rl.Finished&&(Li(b)||(y.value="hidden",d(c),f()))})))}return en(()=>{Bn([n],(A,N,F)=>{I(F),h.value=!1},{immediate:!0})}),qr(Hl,b),Rh(jt(()=>so(y.value,{visible:Gr.Open,hidden:Gr.Closed})|v.value)),()=>{let{appear:A,show:N,enter:F,enterFrom:B,enterTo:W,entered:H,leave:V,leaveFrom:K,leaveTo:J,...le}=r,T={ref:g},D={...le,...a.value&&n.value&&Ai.isServer?{class:Jn([w.class,le.class,...j,...M])}:{}};return Ao({theirProps:D,ourProps:T,slot:{},slots:t,attrs:w,features:Uh,visible:y.value==="visible",name:"TransitionChild"})}}}),W_=z_,Bh=gr({inheritAttrs:!1,props:{as:{type:[Object,String],default:"div"},show:{type:[Boolean],default:null},unmount:{type:[Boolean],default:!0},appear:{type:[Boolean],default:!1},enter:{type:[String],default:""},enterFrom:{type:[String],default:""},enterTo:{type:[String],default:""},entered:{type:[String],default:""},leave:{type:[String],default:""},leaveFrom:{type:[String],default:""},leaveTo:{type:[String],default:""}},emits:{beforeEnter:()=>!0,afterEnter:()=>!0,beforeLeave:()=>!0,afterLeave:()=>!0},setup(r,{emit:i,attrs:w,slots:t}){let x=Bl(),v=jt(()=>r.show===null&&x!==null?(x.value&Gr.Open)===Gr.Open:r.show);fn(()=>{if(![!0,!1].includes(v.value))throw new Error('A is used but it is missing a `:show="true | false"` prop.')});let s=mt(v.value?"visible":"hidden"),u=Nh(()=>{s.value="hidden"}),o=mt(!0),f={show:v,appear:jt(()=>r.appear||!o.value)};return en(()=>{fn(()=>{o.value=!1,v.value?s.value="visible":Li(u)||(s.value="hidden")})}),qr(Hl,u),qr(Vl,f),()=>{let g=Dh(r,["show","appear","unmount","onBeforeEnter","onBeforeLeave","onAfterEnter","onAfterLeave"]),m={unmount:r.unmount};return Ao({ourProps:{...m,as:"template"},theirProps:{},slot:{},slots:{...t,default:()=>[or(W_,{onBeforeEnter:()=>i("beforeEnter"),onAfterEnter:()=>i("afterEnter"),onBeforeLeave:()=>i("beforeLeave"),onAfterLeave:()=>i("afterLeave"),...w,...m,...g},t.default)]},attrs:{},features:Uh,visible:s.value==="visible",name:"Transition"})}}});const q_={},X_={class:"flex min-h-screen flex-col bg-background font-display"},Y_={class:"mt-4 flex-1"},$_={class:"flex justify-center"};function Z_(r,i){const w=D_,t=Bh;return jr(),bs("body",X_,[ft(w),Pt("main",Y_,[Pt("div",$_,[ft(t,{show:"",appear:"",as:"template",enter:"transition transform duration-300 ease-out","enter-from":"translate-x-8 opacity-0","enter-to":"translate-x-0 opacity-100",leave:"transition transform duration-300 ease-in","leave-from":"opacity-100","leave-to":"-translate-x-8 opacity-0"},{default:Ur(()=>i[0]||(i[0]=[Pt("div",{class:"rounded-xl bg-black/50 p-6 text-center shadow-lg"},[Pt("div",{class:"text-6xl font-extrabold tracking-widest text-white"}," Yikes! "),Pt("div",{class:"text-base text-gray-200"}," Either the page you're looking for doesn't exist, or something has gone terribly wrong. ")],-1)])),_:1})])])])}const K_=kh(q_,[["render",Z_]]),rd={__name:"nuxt-root",setup(r){const i=()=>null,w=Dt(),t=w.deferHydration();if(w.isHydrating){const u=w.hooks.hookOnce("app:error",t);Xr().beforeEach(u)}const x=!1;qr(xs,Ti()),w.hooks.callHookWith(u=>u.map(o=>o()),"vue:setup");const v=ki();Wd((u,o,f)=>{if(w.hooks.callHook("vue:error",u,o,f).catch(g=>console.error("[nuxt] Error in `vue:error` hook",g)),av(u)&&(u.fatal||u.unhandled))return w.runWithContext(()=>bo(u)),!1});const s=!1;return(u,o)=>(jr(),Dn(jl,{onResolve:Vt(t)},{default:Ur(()=>[Vt(v)?(jr(),Dn(Vt(K_),{key:0,error:Vt(v)},null,8,["error"])):Vt(s)?(jr(),Dn(Vt(i),{key:1,context:Vt(s)},null,8,["context"])):Vt(x)?(jr(),Dn(_m(Vt(x)),{key:2})):(jr(),Dn(Vt(N1),{key:3}))]),_:1},8,["onResolve"]))}};let nd;{let r;nd=async function(){var s,u;if(r)return r;const t=!!((s=window.__NUXT__)!=null&&s.serverRendered||((u=document.getElementById("__NUXT_DATA__"))==null?void 0:u.dataset.ssr)==="true")?By(rd):Uy(rd),x=Wg({vueApp:t});async function v(o){await x.callHook("app:error",o),x.payload.error=x.payload.error||Mi(o)}t.config.errorHandler=v;try{await Xg(x,M1)}catch(o){v(o)}try{await x.hooks.callHook("app:created",t),await x.hooks.callHook("app:beforeMount",t),t.mount(u0),await x.hooks.callHook("app:mounted",t),await Hr()}catch(o){v(o)}return t.config.errorHandler===v&&(t.config.errorHandler=void 0),t},r=nd().catch(i=>{throw console.error("Error while mounting app:",i),i})}export{Mi as $,qn as A,cw as B,rw as C,lw as D,nr as E,mr as F,Hr as G,t0 as H,Ei as I,sw as J,ai as K,or as L,rt as M,Yp as N,Dt as O,tw as P,hg as Q,fc as R,Bh as S,El as T,Si as U,ji as V,uw as W,os as X,pm as Y,Q_ as Z,W1 as _,Vt as a,ao as a0,_p as a1,vt as a2,bm as a3,no as a4,$t as a5,si as a6,ew as a7,ow as a8,ll as a9,_m as aa,D_ as ab,Vs as ac,Pt as b,bs as c,gr as d,Dn as e,Ur as f,Ko as g,aw as h,ft as i,mt as j,jt as k,Jn as l,kh as m,sv as n,jr as o,ry as p,en as q,nw as r,z_ as s,vp as t,Ti as u,Bn as v,iw as w,gs as x,vs as y,J_ as z}; diff --git a/_nuxt/CmpoAw97.js b/_nuxt/Ce34VGij.js similarity index 76% rename from _nuxt/CmpoAw97.js rename to _nuxt/Ce34VGij.js index 5c84aef1..b4786357 100644 --- a/_nuxt/CmpoAw97.js +++ b/_nuxt/Ce34VGij.js @@ -1,2 +1,2 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./36DYiIQe.js","./CZZfhpmp.js","./C-v3KzvZ.js","./B2jTtLqC.js","./DvDH6DOc.js"])))=>i.map(i=>d[i]); -import{Q as $,I as h,R as P,U as b,V as C,M as E}from"./CZZfhpmp.js";import{h as l}from"./DvDH6DOc.js";import{u as m}from"./B2jTtLqC.js";const d=(t,r)=>r.split(".").reduce((n,i)=>n&&n[i],t),p=(t,r)=>Object.keys(t).filter(r).reduce((n,i)=>Object.assign(n,{[i]:t[i]}),{}),B=t=>r=>t&&t.length?p(r,n=>!t.includes(n)):r,j=t=>r=>Array.isArray(r)?r.map(n=>t(n)):t(r),w=t=>{const r=[],n=[];for(const i of t)["$","_"].includes(i)?r.push(i):n.push(i);return{prefixes:r,properties:n}},q=(t=[])=>r=>{if(t.length===0||!r)return r;const{prefixes:n,properties:i}=w(t);return p(r,o=>!i.includes(o)&&!n.includes(o[0]))},I=(t=[])=>r=>{if(t.length===0||!r)return r;const{prefixes:n,properties:i}=w(t);return p(r,o=>i.includes(o)||n.includes(o[0]))},Q=(t,r)=>{const n=new Intl.Collator(r.$locale,{numeric:r.$numeric,caseFirst:r.$caseFirst,sensitivity:r.$sensitivity}),i=Object.keys(r).filter(o=>!o.startsWith("$"));for(const o of i)t=t.sort((a,e)=>{const s=[d(a,o),d(e,o)].map(c=>{if(c!==null)return c instanceof Date?c.toISOString():c});return r[o]===-1&&s.reverse(),n.compare(s[0],s[1])});return t},F=(t,r="Expected an array")=>{if(!Array.isArray(t))throw new TypeError(r)},u=t=>Array.isArray(t)?t:[void 0,null].includes(t)?[]:[t],S=["sort","where","only","without"];function x(t,r={}){const n={};for(const e of Object.keys(r.initialParams||{}))n[e]=S.includes(e)?u(r.initialParams[e]):r.initialParams[e];const i=(e,s=c=>c)=>(...c)=>(n[e]=s(...c),a),o=e=>{var s;return r.legacy?e!=null&&e.surround?e.surround:e&&(e!=null&&e.dirConfig&&(e.result={_path:(s=e.dirConfig)==null?void 0:s._path,...e.result,_dir:e.dirConfig}),e!=null&&e._path||Array.isArray(e)||!Object.prototype.hasOwnProperty.call(e,"result")?e:e==null?void 0:e.result):e},a={params:()=>({...n,...n.where?{where:[...u(n.where)]}:{},...n.sort?{sort:[...u(n.sort)]}:{}}),only:i("only",u),without:i("without",u),where:i("where",e=>[...u(n.where),...u(e)]),sort:i("sort",e=>[...u(n.sort),...u(e)]),limit:i("limit",e=>parseInt(String(e),10)),skip:i("skip",e=>parseInt(String(e),10)),find:()=>t(a).then(o),findOne:()=>t(i("first")(!0)).then(o),count:()=>t(i("count")(!0)).then(o),locale:e=>a.where({_locale:e}),withSurround:i("surround",(e,s)=>({query:e,...s})),withDirConfig:()=>i("dirConfig")(!0)};return r.legacy&&(a.findSurround=(e,s)=>a.withSurround(e,s).find().then(o)),a}function g(t){return JSON.stringify(t,A)}function A(t,r){return r instanceof RegExp?`--REGEX ${r.toString()}`:r}const O=t=>{let r=g(t);return r=typeof Buffer<"u"?Buffer.from(r).toString("base64"):btoa(r),r=r.replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,""),(r.match(/.{1,100}/g)||[]).join("/")},y=t=>$(t,h().public.content.api.baseURL),U=()=>{throw console.warn("useContent is only accessible when you are using `documentDriven` mode."),console.warn("Learn more by visiting: https://content.nuxt.com/document-driven"),new Error("useContent is only accessible when you are using `documentDriven` mode.")},D=()=>{const{experimental:t}=h().public.content;return t.clientDB?!0:m().isEnabled()},R=()=>async t=>{const{content:r}=h().public,n=t.params(),i=r.experimental.stripQueryParameters?y(`/query/${`${l(n)}.${r.integrity}`}/${O(n)}.json`):y(`/query/${l(n)}.${r.integrity}.json`);if(D())return(await E(()=>import("./36DYiIQe.js"),__vite__mapDeps([0,1,2,3,4]),import.meta.url).then(e=>e.useContentDatabase())).fetch(t);const o=await $fetch(i,{method:"GET",responseType:"json",params:r.experimental.stripQueryParameters?void 0:{_params:g(n),previewToken:m().getPreviewToken()}});if(typeof o=="string"&&o.startsWith(""))throw new Error("Not found");return o};function G(t,...r){const{content:n}=h().public,i=x(R(),{initialParams:typeof t!="string"?t:{},legacy:!0});let o;typeof t=="string"&&(o=P(b(t,...r)));const a=i.params;return i.params=()=>{var s,c,f;const e=a();return o&&(e.where=e.where||[],e.first&&(e.where||[]).length===0?e.where.push({_path:C(o)}):e.where.push({_path:new RegExp(`^${o.replace(/[-[\]{}()*+.,^$\s/]/g,"\\$&")}`)})),(s=e.sort)!=null&&s.length||(e.sort=[{_stem:1,$numeric:!0}]),n.locales.length&&((f=(c=e.where)==null?void 0:c.find(_=>_._locale))!=null&&f._locale||(e.where=e.where||[],e.where.push({_locale:n.defaultLocale}))),e},i}export{F as a,u as b,Q as c,j as d,O as e,q as f,d as g,I as h,x as i,g as j,B as o,G as q,D as s,U as u,y as w}; +const __vite__fileDeps=["./BwID1M5A.js","./K1dcBiIN.js","./C-v3KzvZ.js","./NnUIAPGH.js","./DvDH6DOc.js"],__vite__mapDeps=i=>i.map(i=>__vite__fileDeps[i]); +import{Q as $,I as h,R as P,U as b,V as C,M as E}from"./K1dcBiIN.js";import{h as l}from"./DvDH6DOc.js";import{u as w}from"./NnUIAPGH.js";const d=(t,r)=>r.split(".").reduce((n,i)=>n&&n[i],t),f=(t,r)=>Object.keys(t).filter(r).reduce((n,i)=>Object.assign(n,{[i]:t[i]}),{}),B=t=>r=>t&&t.length?f(r,n=>!t.includes(n)):r,j=t=>r=>Array.isArray(r)?r.map(n=>t(n)):t(r),m=t=>{const r=[],n=[];for(const i of t)["$","_"].includes(i)?r.push(i):n.push(i);return{prefixes:r,properties:n}},q=(t=[])=>r=>{if(t.length===0||!r)return r;const{prefixes:n,properties:i}=m(t);return f(r,o=>!i.includes(o)&&!n.includes(o[0]))},I=(t=[])=>r=>{if(t.length===0||!r)return r;const{prefixes:n,properties:i}=m(t);return f(r,o=>i.includes(o)||n.includes(o[0]))},Q=(t,r)=>{const n=new Intl.Collator(r.$locale,{numeric:r.$numeric,caseFirst:r.$caseFirst,sensitivity:r.$sensitivity}),i=Object.keys(r).filter(o=>!o.startsWith("$"));for(const o of i)t=t.sort((a,e)=>{const s=[d(a,o),d(e,o)].map(c=>{if(c!==null)return c instanceof Date?c.toISOString():c});return r[o]===-1&&s.reverse(),n.compare(s[0],s[1])});return t},F=(t,r="Expected an array")=>{if(!Array.isArray(t))throw new TypeError(r)},u=t=>Array.isArray(t)?t:[void 0,null].includes(t)?[]:[t],S=["sort","where","only","without"];function x(t,r={}){const n={};for(const e of Object.keys(r.initialParams||{}))n[e]=S.includes(e)?u(r.initialParams[e]):r.initialParams[e];const i=(e,s=c=>c)=>(...c)=>(n[e]=s(...c),a),o=e=>{var s;return r.legacy?e!=null&&e.surround?e.surround:e&&(e!=null&&e.dirConfig&&(e.result={_path:(s=e.dirConfig)==null?void 0:s._path,...e.result,_dir:e.dirConfig}),e!=null&&e._path||Array.isArray(e)||!Object.prototype.hasOwnProperty.call(e,"result")?e:e==null?void 0:e.result):e},a={params:()=>({...n,...n.where?{where:[...u(n.where)]}:{},...n.sort?{sort:[...u(n.sort)]}:{}}),only:i("only",u),without:i("without",u),where:i("where",e=>[...u(n.where),...u(e)]),sort:i("sort",e=>[...u(n.sort),...u(e)]),limit:i("limit",e=>parseInt(String(e),10)),skip:i("skip",e=>parseInt(String(e),10)),find:()=>t(a).then(o),findOne:()=>t(i("first")(!0)).then(o),count:()=>t(i("count")(!0)).then(o),locale:e=>a.where({_locale:e}),withSurround:i("surround",(e,s)=>({query:e,...s})),withDirConfig:()=>i("dirConfig")(!0)};return r.legacy&&(a.findSurround=(e,s)=>a.withSurround(e,s).find().then(o)),a}function g(t){return JSON.stringify(t,A)}function A(t,r){return r instanceof RegExp?`--REGEX ${r.toString()}`:r}const O=t=>{let r=g(t);return r=typeof Buffer<"u"?Buffer.from(r).toString("base64"):btoa(r),r=r.replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,""),(r.match(/.{1,100}/g)||[]).join("/")},y=t=>$(t,h().public.content.api.baseURL),U=()=>{throw console.warn("useContent is only accessible when you are using `documentDriven` mode."),console.warn("Learn more by visiting: https://content.nuxt.com/document-driven"),new Error("useContent is only accessible when you are using `documentDriven` mode.")},D=()=>{const{experimental:t}=h().public.content;return t.clientDB?!0:w().isEnabled()},R=()=>async t=>{const{content:r}=h().public,n=t.params(),i=r.experimental.stripQueryParameters?y(`/query/${`${l(n)}.${r.integrity}`}/${O(n)}.json`):y(`/query/${l(n)}.${r.integrity}.json`);if(D())return(await E(()=>import("./BwID1M5A.js"),__vite__mapDeps([0,1,2,3,4]),import.meta.url).then(e=>e.useContentDatabase())).fetch(t);const o=await $fetch(i,{method:"GET",responseType:"json",params:r.experimental.stripQueryParameters?void 0:{_params:g(n),previewToken:w().getPreviewToken()}});if(typeof o=="string"&&o.startsWith(""))throw new Error("Not found");return o};function G(t,...r){const{content:n}=h().public,i=x(R(),{initialParams:typeof t!="string"?t:{},legacy:!0});let o;typeof t=="string"&&(o=P(b(t,...r)));const a=i.params;return i.params=()=>{var s,c,p;const e=a();return o&&(e.where=e.where||[],e.first&&(e.where||[]).length===0?e.where.push({_path:C(o)}):e.where.push({_path:new RegExp(`^${o.replace(/[-[\]{}()*+.,^$\s/]/g,"\\$&")}`)})),(s=e.sort)!=null&&s.length||(e.sort=[{_file:1,$numeric:!0}]),n.locales.length&&((p=(c=e.where)==null?void 0:c.find(_=>_._locale))!=null&&p._locale||(e.where=e.where||[],e.where.push({_locale:n.defaultLocale}))),e},i}export{F as a,u as b,Q as c,j as d,O as e,q as f,d as g,I as h,x as i,g as j,B as o,G as q,D as s,U as u,y as w}; diff --git a/_nuxt/CfFW-P5d.js b/_nuxt/CfFW-P5d.js new file mode 100644 index 00000000..ee93cd98 --- /dev/null +++ b/_nuxt/CfFW-P5d.js @@ -0,0 +1 @@ +import{d as o,a as s,o as n,c as r,g as e,h as a,b as t}from"./K1dcBiIN.js";const c={key:0},i=t("code",null,"script",-1),d=t("code",null,"ProseScript",-1),f=o({__name:"ProseScript",props:{src:{type:String,default:""}},setup(l){return(_,m)=>s(!1)?(n(),r("div",c,[e(" Rendering the "),i,e(" element is dangerous and is disabled by default. Consider implementing your own "),d,e(" element to have control over script rendering. ")])):a("",!0)}});export{f as default}; diff --git a/_nuxt/BdajRVA-.js b/_nuxt/CiJ7X6_i.js similarity index 71% rename from _nuxt/BdajRVA-.js rename to _nuxt/CiJ7X6_i.js index 8c299522..add1dd87 100644 --- a/_nuxt/BdajRVA-.js +++ b/_nuxt/CiJ7X6_i.js @@ -1 +1 @@ -import{m as s,c as h,p as c,o as l}from"./CZZfhpmp.js";const a=["#FFBA08","#FAA307","#F48C06","#E85D04","#DC2F02","#D00000","#9D0208","#6A040F","#370617","#03071E"];class o{constructor(){this.parent=void 0,this.children=[],this.orientation="h",this.x=0,this.y=0,this.w=500,this.h=500}add(i){i.parent=this,this.children.push(i),this.children.forEach((n,r)=>{if(this.orientation==="h"){const e=this.w/this.children.length,t=this.x+e*r;n.x=t,n.y=this.y,n.w=e,n.h=this.h}else if(this.orientation==="v"){const e=this.h/this.children.length,t=this.y+e*r;n.x=this.x,n.y=t,n.w=this.w,n.h=e}})}render(i){i.rect(this.x,this.y,this.w,this.h),this.children.forEach((n,r)=>{i.fill(a[r%9]),n.render(i)})}traverseForPoint(i,n){if(this.children.length===0)return this;for(let r=0;r=e.x&&i<=e.x+e.w&&n>=e.y&&n<=e.y+e.h)return e.children.length===0?e:e.traverseForPoint(i,n)}}}const f={data(){return{}},mounted(){const d=i=>{const e=new o;for(let t=0;t<5;t++)e.add(new o);e.children[0].orientation="v";for(let t=0;t<3;t++)e.children[0].add(new o);e.children[0].children[2].orientation="v";for(let t=0;t<4;t++)e.children[0].children[2].add(new o);e.children[1].orientation="v";for(let t=0;t<3;t++)e.children[1].add(new o);for(let t=0;t<9;t++)e.children[1].children[0].add(new o);e.children[3].orientation="v";for(let t=0;t<3;t++)e.children[3].add(new o);e.children[3].children[2].orientation="v";for(let t=0;t<9;t++)e.children[3].children[2].add(new o);i.setup=()=>{i.createCanvas(500,500),i.noLoop(),i.stroke(255),i.strokeWeight(2),e.render(i)},i.mouseClicked=()=>{const t=e.traverseForPoint(i.mouseX,i.mouseY);t&&(t.add(new o),t.add(new o),t.render(i))}};new this.$p5(d,"canvas")}},v={class:"select-none bg-gradient-to-b from-green-800 to-gray-800"};function w(d,i,n,r,e,t){return l(),h("div",v,i[0]||(i[0]=[c('
        m-ary tree based tiling
        ',1)]))}const m=s(f,[["render",w]]);export{m as default}; +import{m as d,c as h,o as c,p as l}from"./K1dcBiIN.js";const a=["#FFBA08","#FAA307","#F48C06","#E85D04","#DC2F02","#D00000","#9D0208","#6A040F","#370617","#03071E"];class o{constructor(){this.parent=void 0,this.children=[],this.orientation="h",this.x=0,this.y=0,this.w=500,this.h=500}add(i){i.parent=this,this.children.push(i),this.children.forEach((n,r)=>{if(this.orientation==="h"){const e=this.w/this.children.length,t=this.x+e*r;n.x=t,n.y=this.y,n.w=e,n.h=this.h}else if(this.orientation==="v"){const e=this.h/this.children.length,t=this.y+e*r;n.x=this.x,n.y=t,n.w=this.w,n.h=e}})}render(i){i.rect(this.x,this.y,this.w,this.h),this.children.forEach((n,r)=>{i.fill(a[r%9]),n.render(i)})}traverseForPoint(i,n){if(this.children.length===0)return this;for(let r=0;r=e.x&&i<=e.x+e.w&&n>=e.y&&n<=e.y+e.h)return e.children.length===0?e:e.traverseForPoint(i,n)}}}const f={data(){return{}},mounted(){const s=i=>{const e=new o;for(let t=0;t<5;t++)e.add(new o);e.children[0].orientation="v";for(let t=0;t<3;t++)e.children[0].add(new o);e.children[0].children[2].orientation="v";for(let t=0;t<4;t++)e.children[0].children[2].add(new o);e.children[1].orientation="v";for(let t=0;t<3;t++)e.children[1].add(new o);for(let t=0;t<9;t++)e.children[1].children[0].add(new o);e.children[3].orientation="v";for(let t=0;t<3;t++)e.children[3].add(new o);e.children[3].children[2].orientation="v";for(let t=0;t<9;t++)e.children[3].children[2].add(new o);i.setup=()=>{i.createCanvas(500,500),i.noLoop(),i.stroke(255),i.strokeWeight(2),e.render(i)},i.mouseClicked=()=>{const t=e.traverseForPoint(i.mouseX,i.mouseY);t&&(t.add(new o),t.add(new o),t.render(i))}};new this.$p5(s,"canvas")}},v={class:"select-none bg-gradient-to-b from-green-800 to-gray-800"},w=l('
        m-ary tree based tiling
        ',1),u=[w];function m(s,i,n,r,e,t){return c(),h("div",v,u)}const _=d(f,[["render",m]]);export{_ as default}; diff --git a/_nuxt/B-Suu3Ve.js b/_nuxt/ClOZFDRl.js similarity index 64% rename from _nuxt/B-Suu3Ve.js rename to _nuxt/ClOZFDRl.js index 861af509..6b329ed8 100644 --- a/_nuxt/B-Suu3Ve.js +++ b/_nuxt/ClOZFDRl.js @@ -1 +1 @@ -import{m as o,o as r,c as t,a8 as s}from"./CZZfhpmp.js";const c={};function n(e,a){return r(),t("th",null,[s(e.$slots,"default")])}const f=o(c,[["render",n]]);export{f as default}; +import{m as o,o as r,c as t,a8 as s}from"./K1dcBiIN.js";const c={};function n(e,a){return r(),t("th",null,[s(e.$slots,"default")])}const f=o(c,[["render",n]]);export{f as default}; diff --git a/_nuxt/Ct3Jmt0b.js b/_nuxt/Ct3Jmt0b.js deleted file mode 100644 index 0b9ddc1f..00000000 --- a/_nuxt/Ct3Jmt0b.js +++ /dev/null @@ -1 +0,0 @@ -import{d as p,I as f,k as i,o as t,c as s,a as u,a8 as n}from"./CZZfhpmp.js";const l=["id"],d=["href"],_=p({__name:"ProseH5",props:{id:{}},setup(r){const a=r,{headings:o}=f().public.mdc,c=i(()=>{var e;return a.id&&(typeof(o==null?void 0:o.anchorLinks)=="boolean"&&(o==null?void 0:o.anchorLinks)===!0||typeof(o==null?void 0:o.anchorLinks)=="object"&&((e=o==null?void 0:o.anchorLinks)==null?void 0:e.h5))});return(e,k)=>(t(),s("h5",{id:e.id},[e.id&&u(c)?(t(),s("a",{key:0,href:`#${e.id}`},[n(e.$slots,"default")],8,d)):n(e.$slots,"default",{key:1})],8,l))}});export{_ as default}; diff --git a/_nuxt/CuOPeUWs.js b/_nuxt/CuOPeUWs.js deleted file mode 100644 index ba683915..00000000 --- a/_nuxt/CuOPeUWs.js +++ /dev/null @@ -1 +0,0 @@ -import{d as F,a0 as ln,a2 as en,k as w,L as D,a3 as on,a4 as P,a5 as tn,a6 as rn,o as an,e as un,a as sn}from"./CZZfhpmp.js";import{p as H,k as cn}from"./C-v3KzvZ.js";import{f as pn}from"./Dnd51l0P.js";import{u as dn}from"./B2jTtLqC.js";class S{constructor(l,o,t){this.property=l,this.normal=o,t&&(this.space=t)}}S.prototype.property={};S.prototype.normal={};S.prototype.space=null;function V(n,l){const o={},t={};let r=-1;for(;++r4&&o.slice(0,4)==="data"&&yn.test(l)){if(l.charAt(4)==="-"){const a=l.slice(5).replace(j,Cn);t="data"+a.charAt(0).toUpperCase()+a.slice(1)}else{const a=l.slice(4);if(!j.test(a)){let i=a.replace(vn,kn);i.charAt(0)!=="-"&&(i="-"+i),l="data"+i}}r=E}return new r(t,l)}function kn(n){return"-"+n.toLowerCase()}function Cn(n){return n.charAt(1).toUpperCase()}const Sn=V([W,q,Y,$,fn],"html");V([W,q,Y,$,mn],"svg");const B=["a","abbr","address","area","article","aside","audio","b","base","bdi","bdo","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","data","datalist","dd","del","details","dfn","dialog","div","dl","dt","em","embed","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","kbd","label","legend","li","link","main","map","mark","math","menu","menuitem","meta","meter","nav","noscript","object","ol","optgroup","option","output","p","param","picture","pre","progress","q","rb","rp","rt","rtc","ruby","s","samp","script","section","select","slot","small","source","span","strong","style","sub","summary","sup","svg","table","tbody","td","template","textarea","tfoot","th","thead","time","title","tr","track","u","ul","var","video","wbr"],T="default",Z=/^@|^v-on:/,J=/^:|^v-bind:/,G=/^v-model/,xn=["select","textarea","input"],wn=Object.fromEntries(["p","a","blockquote","code","pre","code","em","h1","h2","h3","h4","h5","h6","hr","img","ul","ol","li","strong","table","thead","tbody","td","th","tr","script"].map(n=>[n,`prose-${n}`])),Pn=F({name:"MDCRenderer",props:{body:{type:Object,required:!0},data:{type:Object,default:()=>({})},class:{type:[String,Object],default:void 0},tag:{type:[String,Boolean],default:void 0},prose:{type:Boolean,default:void 0},components:{type:Object,default:()=>({})},unwrap:{type:[Boolean,String],default:!1}},async setup(n){var i,s,c,h,f,p,y,z;const l=(c=(s=(i=ln())==null?void 0:i.appContext)==null?void 0:s.app)==null?void 0:c.$nuxt,o=(l==null?void 0:l.$route)||(l==null?void 0:l._route),{mdc:t}=((h=l==null?void 0:l.$config)==null?void 0:h.public)||{},r={...(f=t==null?void 0:t.components)!=null&&f.prose&&n.prose!==!1?wn:{},...((p=t==null?void 0:t.components)==null?void 0:p.map)||{},...en(((z=(y=n.data)==null?void 0:y.mdc)==null?void 0:z.components)||{}),...n.components},a=w(()=>{var _;const nn=(((_=n.body)==null?void 0:_.children)||[]).map(x=>x.tag||x.type).filter(x=>!B.includes(x));return Array.from(new Set(nn)).sort().join(".")});return await zn(n.body,{tags:r}),{tags:r,contentKey:a,route:o}},render(n){var p,y;const{tags:l,tag:o,body:t,data:r,contentKey:a,route:i,unwrap:s}=n;if(!t)return null;const c={...r,tags:l,$route:i},h=o!==!1?U(o||((p=c.component)==null?void 0:p.name)||c.component||"div"):void 0;return h?D(h,{...(y=c.component)==null?void 0:y.props,class:n.class,...this.$attrs,key:a},{default:f}):f==null?void 0:f();function f(){return s?pn(A(t,D,c,c).default(),typeof s=="string"?s.split(" "):["*"]):A(t,D,c,c).default()}}});function On(n,l,o,t={}){if(n.type==="text")return l(P,n.value);if(n.type==="comment")return l(tn,null,n.value);const r=n.tag,a=Q(n,o.tags);if(n.tag==="binding")return Dn(n,l,o,t);const i=U(a);typeof i=="object"&&(i.tag=r);const s=Ln(n,o);return l(i,s,A(n,l,o,{...t,...s}))}function Dn(n,l,o,t={}){var h,f;const r={...t,$document:o,$doc:o},a=/\.|\[(\d+)\]/,s=((h=n.props)==null?void 0:h.value.trim().split(a).filter(Boolean)).reduce((p,y)=>{if(p&&y in p)return typeof p[y]=="function"?p[y]():p[y]},r),c=(f=n.props)==null?void 0:f.defaultValue;return l(P,s??c??"")}function A(n,l,o,t){const a=(n.children||[]).reduce((s,c)=>{if(!Bn(c))return s[T].push(c),s;const h=En(c);return s[h]=s[h]||[],c.type==="element"&&s[h].push(...c.children||[]),s},{[T]:[]});return Object.entries(a).reduce((s,[c,h])=>(h.length&&(s[c]=()=>{const f=h.map(p=>On(p,l,o,t));return Un(f)}),s),{})}function Ln(n,l){const{tag:o="",props:t={}}=n;return Object.keys(t).reduce(function(r,a){if(a==="__ignoreMap")return r;const i=t[a];if(G.test(a)&&!xn.includes(o))return Mn(a,i,r,l);if(a==="v-bind")return Rn(a,i,r,l);if(Z.test(a))return Tn(a,i,r,l);if(J.test(a))return An(a,i,r,l);const{attribute:s}=bn(Sn,a);return Array.isArray(i)&&i.every(c=>typeof c=="string")?(r[s]=i.join(" "),r):(r[s]=i,r)},{})}function Mn(n,l,o,t){const r=p=>+p,a=p=>p.trim(),i=p=>p,s=n.replace(G,"").split(".").filter(p=>p).reduce((p,y)=>(p[y]=!0,p),{}),c="value",h=s.lazy?"change":"input",f=s.number?r:s.trim?a:i;return o[c]=O(l,t),o.on=o.on||{},o.on[h]=p=>t[l]=f(p),o}function Rn(n,l,o,t){const r=O(l,t);return o=Object.assign(o,r),o}function Tn(n,l,o,t){return n=n.replace(Z,""),o.on=o.on||{},o.on[n]=()=>O(l,t),o}function An(n,l,o,t){return n=n.replace(J,""),o[n]=O(l,t),o}const U=n=>{if(!B.includes(n)&&!(n!=null&&n.render)&&!(n!=null&&n.ssrRender)){const l=on(H(n),!1);if(typeof l=="object")return l}return n};function O(n,l){const o=n.split(".").reduce((t,r)=>typeof t=="object"?t[r]:void 0,l);return typeof o>"u"?rn(n):o}function En(n){let l="";for(const o of Object.keys(n.props||{}))if(!(!o.startsWith("#")&&!o.startsWith("v-slot:"))){l=o.split(/[:#]/,2)[1];break}return l||T}function Bn(n){return n.tag==="template"}function Un(n){const l=[];for(const o of n){const t=l[l.length-1];o.type===P&&(t==null?void 0:t.type)===P?t.children=t.children+o.children:l.push(o)}return l}async function zn(n,l){if(!n)return;const o=Array.from(new Set(t(n,l)));await Promise.all(o.map(async r=>{if(r!=null&&r.render||r!=null&&r.ssrRender||r!=null&&r.__ssrInlineRender)return;const a=U(r);a!=null&&a.__asyncLoader&&!a.__asyncResolved&&await a.__asyncLoader()}));function t(r,a){const i=r.tag;if(r.type==="text"||i==="binding"||r.type==="comment")return[];const s=Q(r,a.tags),c=[];r.type!=="root"&&!B.includes(s)&&c.push(s);for(const h of r.children||[])c.push(...t(h,a));return c}}function Q(n,l){var t;const o=n.tag;return!o||typeof((t=n.props)==null?void 0:t.__ignoreMap)<"u"?o:l[o]||l[H(o)]||l[cn(n.tag)]||o}const _n=Pn,Vn=F({__name:"ContentRendererMarkdown",props:{value:{type:Object,required:!0},excerpt:{type:Boolean,default:!1},tag:{type:String,default:"div"},components:{type:Object,default:()=>({})},data:{type:Object,default:()=>({})}},setup(n){const l=n,o=dn().isEnabled(),t=w(()=>{let i=l.value.body||l.value;return l.excerpt&&l.value.excerpt&&(i=l.value.excerpt),i}),r=w(()=>{const{body:i,excerpt:s,...c}=l.value;return{...c,...l.data}}),a=w(()=>({...l.components,...r.value._components||{}}));return(i,s)=>{const c=_n;return an(),un(c,{body:t.value,data:r.value,tag:n.tag,components:a.value,"data-content-id":sn(o)?n.value._id:void 0},null,8,["body","data","tag","components","data-content-id"])}}});export{Vn as _}; diff --git a/_nuxt/CwlYhM_w.js b/_nuxt/CwlYhM_w.js new file mode 100644 index 00000000..e816eabb --- /dev/null +++ b/_nuxt/CwlYhM_w.js @@ -0,0 +1 @@ +import{m as _,c as s,g as l,b as e,l as v,t as d,F as c,r as h,i as b,f as y,T as M,o as r,h as g}from"./K1dcBiIN.js";var O={};Object.defineProperty(O,"__esModule",{value:!0});var p=O.identify=void 0;const u=["C","C# / Db","D","D# / Eb","E","F","F# / Gb","G","G# / Ab","A","A# / Bb","B"],x={"0 1":{name:"No 3 Major 7",rootOffset:1},"0 2":{name:"No 3 7",rootOffset:2},"0 3":{name:"Minor",rootOffset:0},"0 4":{name:"",rootOffset:0},"0 5":{name:"5",rootOffset:5},"0 6":{name:"7",rootOffset:2},"0 7":{name:"5",rootOffset:0},"0 8":{name:"",rootOffset:8},"0 9":{name:"Minor",rootOffset:9},"0 10":{name:"No 3 7",rootOffset:0},"0 11":{name:"No 3 Major 7",rootOffset:0},"0 2 7":{name:"Suspended 2",rootOffset:0},"0 3 6 10":{name:"Half-diminished 7",rootOffset:0},"0 3 6 9":{name:"Diminished 7",rootOffset:0},"0 3 6":{name:"Diminished",rootOffset:0},"0 3 7 10":{name:"Minor 7",rootOffset:0},"0 3 7 11":{name:"Minor-major 7",rootOffset:0},"0 3 7 9":{name:"Minor 6",rootOffset:0},"0 3 7":{name:"Minor",rootOffset:0},"0 4 10":{name:"7",rootOffset:0},"0 4 11":{name:"Major 7",rootOffset:0},"0 4 5 7":{name:"Add 11",rootOffset:0},"0 4 6":{name:"Flat 5",rootOffset:0},"0 4 7 10":{name:"Dominant 7",rootOffset:0},"0 4 7 11":{name:"Major 7",rootOffset:0},"0 4 7 9":{name:"Major 6",rootOffset:0},"0 4 7":{name:"",rootOffset:0},"0 4 8 10":{name:"Augmented 7",rootOffset:0},"0 4 8":{name:"Augmented",rootOffset:0},"0 5 7":{name:"Suspended 4",rootOffset:0},"0 5 8":{name:"Minor",rootOffset:5},"0 5 9":{name:"",rootOffset:5},"0 4 9":{name:"Minor",rootOffset:9},"0 3 8":{name:"",rootOffset:8},"0 1 5":{name:"Major 7",rootOffset:1},"0 2 6":{name:"Major 7",rootOffset:2},"0 4 5":{name:"5 Major 7",rootOffset:5},"0 1 2":{name:"No 3 7 Major 7",rootOffset:2},"0 1 3":{name:"Minor Add Flat 9",rootOffset:0},"0 1 6":{name:"5 Sharp 11",rootOffset:6},"0 1 7":{name:"5 Add Flat 9",rootOffset:0},"0 1 8":{name:"5 Major 7",rootOffset:1},"0 1 9":{name:"Sharp 9",rootOffset:9},"0 1 10":{name:"Minor Add 9",rootOffset:10},"0 1 11":{name:"No 3 7 Major 7",rootOffset:1},"0 2 10":{name:"Add 9",rootOffset:10},"0 2 11":{name:"Minor Add Flat 9",rootOffset:11},"0 2 3":{name:"Minor Add 9",rootOffset:0},"0 2 4":{name:"Add 9",rootOffset:0},"0 2 5":{name:"Minor 7",rootOffset:2},"0 2 8":{name:"Flat 5",rootOffset:8},"0 2 9":{name:"5 7",rootOffset:2},"0 3 10":{name:"Minor 7",rootOffset:0},"0 3 4":{name:"Sharp 9",rootOffset:0},"0 3 5":{name:"5 7",rootOffset:5},"0 3 9":{name:"Minor 6",rootOffset:0},"0 5 10":{name:"Suspended 2",rootOffset:10},"0 5 11":{name:"5 Sharp 11",rootOffset:5},"0 5 6":{name:"5 Add Flat 9",rootOffset:5},"0 6 10":{name:"Flat 5",rootOffset:6},"0 6 7":{name:"5 Sharp 11",rootOffset:0},"0 6 8":{name:"7",rootOffset:8},"0 6 9":{name:"Minor 6",rootOffset:9},"0 7 10":{name:"5 7",rootOffset:0},"0 7 11":{name:"5 Major 7",rootOffset:0},"0 7 8":{name:"Major 7",rootOffset:8},"0 7 9":{name:"Minor 7",rootOffset:9},"0 8 10":{name:"Add 9",rootOffset:8},"0 8 11":{name:"Sharp 9",rootOffset:8},"0 9 10":{name:"Minor Add Flat 9",rootOffset:9},"0 9 11":{name:"Minor Add 9",rootOffset:9},"0 10 11":{name:"No 3 7 Major 7",rootOffset:0},"0 1 4":{name:"Sharp 9",rootOffset:9},"0 8 9":{name:"Sharp 9",rootOffset:5},"0 6 11":{name:"7/13",rootOffset:2},"0 3 11":{name:"Sharp 9",rootOffset:8}};function w(f){const a=f.map(t=>typeof t=="number"?t:u.indexOf(t));if(a.some(t=>t<0))throw new Error("Unsupported note letter or number provided");if(new Set(a.map(t=>t%12)).size===1)return{name:u[a[0]%12]};const i=a.sort((t,o)=>t-o)[0]%12,m=[...new Set(a.map(t=>(t-i)%12).sort((t,o)=>t-o))],n=x[m.join(" ")];if(n){const t=(i+n.rootOffset)%12,o=u[t];return{name:n.name!==""?`${o} ${n.name}`:o,interval:m,root:t}}else return{name:void 0}}p=O.identify=w;const A={mounted(){typeof navigator.requestMIDIAccess<"u"&&navigator.requestMIDIAccess().then(f=>{this.midi=f,this.midi.inputs.forEach(a=>{a.onmidimessage=i=>{i.data[0]===144&&(this.activeKeys.set(i.data[1],i.data),this.$forceUpdate()),i.data[0]===128&&(this.activeKeys.delete(i.data[1]),this.$forceUpdate())}})},f=>{console.error(f)})},data(){return{tooltip:!1,midi:void 0,activeKeys:new Map}},computed:{inputs(){if(typeof this.midi<"u")return Array.from(this.midi.inputs.values())},outputs(){if(typeof this.midi<"u")return Array.from(this.midi.outputs.values())}},methods:{orderedNotes(){return Array.from(this.activeKeys.keys()).sort()},chord(){const f=Array.from(this.activeKeys.keys());return p(f).name}}},k={class:"h-2/3 bg-gradient-to-b from-green-900 via-purple-900 to-indigo-900 text-white"},N={key:0,class:"p-4 text-center font-light tracking-wide"},S=e("a",{class:"text-blue-500 underline",href:"https://developer.mozilla.org/en-US/docs/Web/API/MIDIMessageEvent#browser_compatibility"},"not supported",-1),j={key:1},I={class:"flex flex-wrap"},D={class:"absolute bottom-16 right-2"},F=e("div",{class:"mb-0 rounded-t-lg border-b border-solid bg-green-600 p-3 font-semibold uppercase text-white opacity-75"}," MIDI Status ",-1),E={class:"p-3 font-mono text-orange-900"},z={class:"mb-2 font-bold"},V={class:"mb-2"},C=e("div",{class:"font-bold"},"Inputs:",-1),B={key:0,class:"p-4 text-center italic"},K={key:1},T={class:"flex-1"},P={class:"flex-1"},U={class:"mb-2"},G=e("div",{class:"font-bold"},"Outputs:",-1),L={key:0,class:"p-4 text-center italic"},q={key:1},H={class:"flex-1"},R={class:"flex-1"},W={class:"absolute bottom-2 right-2"},Y=e("svg",{xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 20 20",class:"h-10 w-10"},[e("g",{fill:"none"},[e("path",{d:"M2.5 4a.5.5 0 0 0-.5.5v11a.5.5 0 0 0 .5.5h15a.5.5 0 0 0 .5-.5v-11a.5.5 0 0 0-.5-.5h-15zm.5 6h2v3.5a.5.5 0 0 0 1 0V10h2v3.5a.5.5 0 0 0 1 0V10h2v3.5a.5.5 0 0 0 1 0V10h2v3.5a.5.5 0 0 0 1 0V10h2v5H3v-5zm2.75-2.5a.75.75 0 1 1 0-1.5a.75.75 0 0 1 0 1.5zm6.25-1a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5zm-3 .251a.75.75 0 1 1-1.5 0a.75.75 0 0 1 1.5 0z",fill:"currentColor"})])],-1),J=[Y],Q={class:"absolute bottom-4 left-4"},X={class:"flex"},Z={class:"grid h-screen place-items-center"},$={class:"text-center text-4xl font-semibold tracking-wide"},ee={key:0};function te(f,a,i,m,n,t){return r(),s("div",k,[typeof n.midi>"u"?(r(),s("div",N,[l(" Unfortunately, the Web MIDI API is "),S,l(" in all browsers... ")])):(r(),s("div",j,[e("div",I,[e("div",D,[e("div",{class:v([{hidden:!n.tooltip,block:n.tooltip},"z-50 max-w-md break-words rounded-lg border-2 border-green-800 bg-yellow-200 text-sm font-normal leading-normal"])},[e("div",null,[F,e("div",E,[e("div",z,[l(" Enabled: "),e("span",null,d(typeof n.midi<"u"?"Yep!":"Nope"),1)]),e("div",V,[C,t.inputs.length===0?(r(),s("div",B," No input devices detected :( ")):(r(),s("div",K,[(r(!0),s(c,null,h(t.inputs,o=>(r(),s("div",{key:o.id,class:"flex"},[e("div",T,d(o.manufacturer),1),e("div",P,d(o.name),1)]))),128))]))]),e("div",U,[G,t.outputs.length===0?(r(),s("div",L," No output devices detected :( ")):(r(),s("div",q,[(r(!0),s(c,null,h(t.outputs,o=>(r(),s("div",{key:o.id,class:"flex"},[e("div",H,d(o.manufacturer),1),e("div",R,d(o.name),1)]))),128))]))])])])],2)]),e("div",W,[e("button",{onClick:a[0]||(a[0]=o=>n.tooltip=!n.tooltip),class:"border-3 rounded-lg border-green-600 bg-green-50 px-1 text-green-600 shadow hover:text-green-500 hover:shadow-lg",type:"button"},J)])]),e("div",Q,[e("div",X,[(r(!0),s(c,null,h(t.orderedNotes(),o=>(r(),s("div",{key:o,class:"p-4"},d(o),1))),128))])]),e("div",Z,[e("div",null,[e("div",$,[b(M,{"enter-active-class":"duration-500 ease-out","enter-class":"opacity-0 transform","enter-to-class":"opacity-100","leave-active-class":"duration-500","leave-class":"opacity-100","leave-to-class":"opacity-0 transform"},{default:y(()=>[n.activeKeys.size>=1?(r(),s("div",ee,d(t.chord()||"?"),1)):g("",!0)]),_:1})])])])]))])}const se=_(A,[["render",te]]);export{se as default}; diff --git a/_nuxt/CxWdTzCB.js b/_nuxt/CxWdTzCB.js new file mode 100644 index 00000000..6d86f765 --- /dev/null +++ b/_nuxt/CxWdTzCB.js @@ -0,0 +1 @@ +import{d as i,I as c,k as p,o as s,c as n,a as u,a8 as t}from"./K1dcBiIN.js";const f=["id"],l=["href"],k=i({__name:"ProseH2",props:{id:{}},setup(a){const r=a,{headings:o}=c().public.mdc,d=p(()=>{var e;return r.id&&((e=o==null?void 0:o.anchorLinks)==null?void 0:e.h2)});return(e,m)=>(s(),n("h2",{id:e.id},[e.id&&u(d)?(s(),n("a",{key:0,href:`#${e.id}`},[t(e.$slots,"default")],8,l)):t(e.$slots,"default",{key:1})],8,f))}});export{k as default}; diff --git a/_nuxt/D-xzt0Hk.js b/_nuxt/D-xzt0Hk.js new file mode 100644 index 00000000..38234595 --- /dev/null +++ b/_nuxt/D-xzt0Hk.js @@ -0,0 +1 @@ +import{_ as m}from"./WSSBFWCz.js";import"./K1dcBiIN.js";export{m as default}; diff --git a/_nuxt/D24cNfD5.js b/_nuxt/D24cNfD5.js new file mode 100644 index 00000000..7f18f371 --- /dev/null +++ b/_nuxt/D24cNfD5.js @@ -0,0 +1 @@ +import{m as w,o as c,c as h,p as y,j as n,q as _,a as s,l as v,i as p,h as u,b as t,t as i,F as x}from"./K1dcBiIN.js";const V={},k={version:"1.1",id:"Layer_1",xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",x:"0px",y:"0px",viewBox:"0 0 1160 1160","enable-background":"new 0 0 1160 1160","xml:space":"preserve"},H=y('',2),M=[H];function S(o,r){return c(),h("svg",k,M)}const C=w(V,[["render",S]]),P=window.setInterval,z={class:"bg-slate-800"},B={class:"flex h-screen items-center justify-center"},j={class:"mb-4 space-y-2 text-sm"},F=t("div",{class:"flex items-center"},[t("div",{class:"flex-none pr-2"},"Name"),t("div",{class:"flex-grow border-b border-dotted"}),t("div",{class:"flex-none pl-2"},"Colton")],-1),N={class:"flex items-center"},W=t("div",{class:"flex-none pr-2"},"Profession",-1),$=t("div",{class:"flex-grow border-b border-dotted"},null,-1),A={class:"flex-none pl-2"},I={class:"flex items-center"},q=t("div",{class:"flex-none pr-2"},"Hobby",-1),D=t("div",{class:"flex-grow border-b border-dotted"},null,-1),E={class:"flex-none pl-2"},L="TL;DR",Y={__name:"card",setup(o){const r=n(!1),a=n(0),l=n(0),f=(e,g)=>e[g%e.length];_(()=>{P(function(){a.value>l.value?l.value+=1:a.value+=1},1500)});const m=["Skydiving","Bungee jumping","Rock climbing","White water rafting","Paragliding","Scuba diving","Base jumping","Mountain biking","Surfing","Snowboarding","Wakeboarding","Motorsports","Parkour","Zip-lining","Off-roading","Cave diving","Kiteboarding","Hang gliding","Free solo climbing","Bull riding","Ice climbing","Wing suit flying","Extreme skiing","Cliff jumping","Cave exploring"],d=["Astronaut","Archaeologist","Professional athlete","Chef","Fashion designer","Film director","Investigative journalist","Marine biologist","Musician","Photographer","Pilot","Professional gamer","Professor","Sculptor","Spy","Stand-up comedian","Surfing instructor","Travel writer","Wildlife photographer","Wine connoisseur","Yacht captain","Yoga instructor","Zookeeper","Adventure tour guide","Art curator"];return(e,g)=>{const b=C;return c(),h(x,null,[s(r)?(c(),h("div",{key:0,class:v(["absolute bottom-2 right-2 h-24 w-24",e.dynamic_bg])},[p(b)],2)):u("",!0),t("main",z,[t("div",B,[t("div",{id:"_card",onClick:g[0]||(g[0]=R=>r.value=!s(r)),class:"md:w-512px w-[350px] border border-white bg-black p-4 font-mono uppercase text-white shadow-xl shadow-yellow-950 transition-all hover:scale-102 hover:cursor-pointer"},[t("div",{class:"mb-2 font-extrabold tracking-wide"},i(L)),t("div",j,[F,t("div",N,[W,$,t("div",A,i(f(d,s(a))),1)]),t("div",I,[q,D,t("div",E,i(f(m,s(l))),1)])])])])])],64)}}};export{Y as default}; diff --git a/_nuxt/D2yfouAe.js b/_nuxt/D2yfouAe.js deleted file mode 100644 index dbf75321..00000000 --- a/_nuxt/D2yfouAe.js +++ /dev/null @@ -1 +0,0 @@ -import{d as f,o as n,c as a,b as t,h as g,g as o,i as r,f as u,F as x,r as b,t as _,_ as v,w,a as y}from"./CZZfhpmp.js";import{_ as k,a as $}from"./BNTwU45X.js";import{q as C}from"./CmpoAw97.js";import"./DvDH6DOc.js";import"./B2jTtLqC.js";const D={class:"container mx-auto pb-8"},S={class:"flex flex-wrap"},A={class:"w-full"},B={class:"lg:text-normal space-y-4 font-medium tracking-wide text-white text-justify sm:text-base"},I=f({__name:"AboutMe",setup(d){return(s,e)=>(n(),a("section",D,[t("div",S,[t("div",A,[t("div",B,[g("",!0),e[1]||(e[1]=t("div",null,[o(" I help educate data engineers while building the future of data orchestration at "),t("a",{class:"border-b-2 border-orange-500",target:"_blank",rel:"noopener noreferrer",href:"https://dagster.io/"},"Dagster"),o(". ")],-1)),e[2]||(e[2]=t("div",null,[o(" Previously, I worked at "),t("a",{class:"border-b-2 border-orange-500",target:"_blank",rel:"noopener noreferrer",href:"https://www.gemini.com/"},"Gemini"),o(" building the data platform that provided company-wide insights into the exchange and business. At Georgetown University's "),t("a",{class:"border-b-2 border-orange-500",target:"_blank",rel:"noopener noreferrer",href:"https://mccourt.georgetown.edu/research/the-massive-data-institute/"},"Massive Data Institute"),o(" building data warehousing, processing solutions, and portals to aid social scientists and researchers to leverage large-scale organic data. And previously I provided consulting for financial institutions and government agencies in the D.C. area around data practices, and identity and access management. ")],-1))])])])]))}}),N={class:"bg-gradient-to-b from-background to-transparent"},P={class:"container mx-auto space-y-4"},L={class:"mb-4 grid grid-cols-1 gap-4 md:grid-cols-2"},M={class:"space-y-4 bg-black/70 p-4 text-white drop-shadow-lg hover:ring-1 hover:ring-white"},V={class:""},q={class:"flex-1 text-lg font-bold md:text-xl"},F={key:0,class:"text-sm font-light text-gray-400"},G={class:"line-clamp-3 text-sm text-gray-300"},T={__name:"BlogPosts",props:{articles:[],show_dates:!1},setup(d){return(s,e)=>{const c=v,m=k;return n(),a("section",N,[t("div",P,[r(c,{to:"/articles",class:"font-mono text-3xl font-semibold text-white underline decoration-orange-500 underline-offset-4 hover:text-orange-500"},{default:u(()=>e[0]||(e[0]=[o(" blog posts ")])),_:1}),t("div",L,[(n(!0),a(x,null,b(d.articles,(i,l)=>(n(),a("div",{key:l},[r(c,{to:i._path,external:""},{default:u(()=>[t("div",M,[t("div",V,[t("div",q,_(i.title),1),d.show_dates?(n(),a("div",F,_(new Date(i.date).toLocaleDateString("en-US",{month:"long",day:"numeric",year:"numeric"})),1)):g("",!0)]),t("div",G,_(i.description),1)])]),_:2},1032,["to"])]))),128))]),t("div",null,[r(m,{to:"/articles"})])])])}}},U={class:"bg-emerald-950 bg-[url('/images/noise.svg')]"},K={__name:"index",async setup(d){let s,e;const c=([s,e]=w(()=>C().only(["_id","_path","title","description","date","img","author","tags"]).sort({date:-1}).limit(4).find()),s=await s,e(),s);return(m,i)=>{const l=I,p=T,h=$;return n(),a("div",null,[r(l),t("div",U,[g("",!0),r(p,{articles:y(c),show_dates:!0},null,8,["articles"]),r(h,{limit:9,showImages:"",linkToPlayground:""})])])}}};export{K as default}; diff --git a/_nuxt/D6go2xuX.js b/_nuxt/D6go2xuX.js deleted file mode 100644 index ff3c0a34..00000000 --- a/_nuxt/D6go2xuX.js +++ /dev/null @@ -1 +0,0 @@ -import{d as p,I as f,k as i,o as t,c as s,a as u,a8 as n}from"./CZZfhpmp.js";const l=["id"],d=["href"],_=p({__name:"ProseH3",props:{id:{}},setup(r){const a=r,{headings:o}=f().public.mdc,c=i(()=>{var e;return a.id&&(typeof(o==null?void 0:o.anchorLinks)=="boolean"&&(o==null?void 0:o.anchorLinks)===!0||typeof(o==null?void 0:o.anchorLinks)=="object"&&((e=o==null?void 0:o.anchorLinks)==null?void 0:e.h3))});return(e,k)=>(t(),s("h3",{id:e.id},[e.id&&u(c)?(t(),s("a",{key:0,href:`#${e.id}`},[n(e.$slots,"default")],8,d)):n(e.$slots,"default",{key:1})],8,l))}});export{_ as default}; diff --git a/_nuxt/DCZXcdSM.js b/_nuxt/DCZXcdSM.js new file mode 100644 index 00000000..28431f3f --- /dev/null +++ b/_nuxt/DCZXcdSM.js @@ -0,0 +1 @@ +import{m as u,c as s,g as r,b as t,l as f,t as n,F as c,r as h,h as m,o}from"./K1dcBiIN.js";const v={mounted(){typeof navigator.requestMIDIAccess<"u"&&navigator.requestMIDIAccess().then(i=>{this.midi=i,this.midi.inputs.forEach(l=>{l.onmidimessage=_=>{this.events.push(_),this.events.length>15&&this.events.shift()}})},i=>{console.error(i)})},data(){return{tooltip:!1,midi:void 0,events:[]}},computed:{inputs(){if(typeof this.midi<"u")return Array.from(this.midi.inputs.values())},outputs(){if(typeof this.midi<"u")return Array.from(this.midi.outputs.values())}},filters:{midiCommand:i=>{switch(i){case 144:return"Note On";case 128:return"Note Off";default:return i}},midiNote:i=>`${["C","C# / Db","D","D# / Eb","E","F","F# / Bb","G","G# / Ab","A","A# / Bb","B"][i%12]} (${Math.floor(i/12)-2})`}},b={class:"h-2/3 bg-gradient-to-b from-green-100 to-green-50"},g={key:0,class:"p-4 text-center font-light tracking-wide"},x=t("a",{class:"text-blue-500 underline",href:"https://developer.mozilla.org/en-US/docs/Web/API/MIDIMessageEvent#browser_compatibility"},"not supported",-1),y={key:1},w={class:"flex flex-wrap"},k={class:"absolute bottom-16 right-2"},I=t("div",{class:"mb-0 rounded-t-lg border-b border-solid bg-green-600 p-3 font-semibold uppercase text-white opacity-75"}," MIDI Status ",-1),M={class:"p-3 font-mono text-orange-900"},N={class:"mb-2 font-bold"},D={class:"mb-2"},C=t("div",{class:"font-bold"},"Inputs:",-1),A={key:0,class:"p-4 text-center italic"},z={key:1},E={class:"flex-1"},V={class:"flex-1"},B={class:"mb-2"},F=t("div",{class:"font-bold"},"Outputs:",-1),S={key:0,class:"p-4 text-center italic"},O={key:1},P={class:"flex-1"},q={class:"flex-1"},G={class:"absolute bottom-2 right-2"},T=t("svg",{xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 20 20",class:"h-10 w-10"},[t("g",{fill:"none"},[t("path",{d:"M2.5 4a.5.5 0 0 0-.5.5v11a.5.5 0 0 0 .5.5h15a.5.5 0 0 0 .5-.5v-11a.5.5 0 0 0-.5-.5h-15zm.5 6h2v3.5a.5.5 0 0 0 1 0V10h2v3.5a.5.5 0 0 0 1 0V10h2v3.5a.5.5 0 0 0 1 0V10h2v3.5a.5.5 0 0 0 1 0V10h2v5H3v-5zm2.75-2.5a.75.75 0 1 1 0-1.5a.75.75 0 0 1 0 1.5zm6.25-1a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5zm-3 .251a.75.75 0 1 1-1.5 0a.75.75 0 0 1 1.5 0z",fill:"currentColor"})])],-1),U=[T],W={class:"container mx-auto p-8"},H=t("div",{class:"font-display text-4xl font-light tracking-wide"}," MIDI Events ",-1),L={class:"w-full table-auto border-2 border-green-800 bg-green-50 text-sm"},R=t("thead",{class:"bg-green-800 font-semibold uppercase text-white"},[t("tr",null,[t("th",{class:"p-2 text-left"},"Timestamp"),t("th",{class:"p-2 text-left"},"Command #"),t("th",{class:"p-2 text-left"},"Command"),t("th",{class:"p-2 text-left"},"Note #"),t("th",{class:"p-2 text-left"},"Note"),t("th",{class:"p-2 text-left"},"Velocity"),t("th",{class:"p-2 text-right"},"MIDI Source")])],-1),Y={class:"divide-y divide-gray-100"},j={key:0},J=t("td",{class:"p-4 text-center italic",colspan:"7"}," Press a key, or turn a knob! ",-1),K=[J],Q={class:"p-2 text-left"},X={class:"p-2 text-left"},Z={class:"p-2 text-left"},$={class:"p-2 text-left"},tt={key:0,class:"p-2 text-left"},et={key:1,class:"p-2 text-left"},st={class:"p-2 text-left"},ot={class:"p-2 text-right"};function it(i,l,_,nt,d,a){return o(),s("div",b,[typeof d.midi>"u"?(o(),s("div",g,[r(" Unfortunately, the Web MIDI API is "),x,r(" in all browsers... ")])):(o(),s("div",y,[t("div",w,[t("div",k,[t("div",{class:f([{hidden:!d.tooltip,block:d.tooltip},"z-50 max-w-md break-words rounded-lg border-2 border-green-800 bg-yellow-200 text-sm font-normal leading-normal"])},[t("div",null,[I,t("div",M,[t("div",N,[r(" Enabled: "),t("span",null,n(typeof d.midi<"u"?"Yep!":"Nope"),1)]),t("div",D,[C,a.inputs.length===0?(o(),s("div",A," No input devices detected :( ")):(o(),s("div",z,[(o(!0),s(c,null,h(a.inputs,e=>(o(),s("div",{key:e.id,class:"flex"},[t("div",E,n(e.manufacturer),1),t("div",V,n(e.name),1)]))),128))]))]),t("div",B,[F,a.outputs.length===0?(o(),s("div",S," No output devices detected :( ")):(o(),s("div",O,[(o(!0),s(c,null,h(a.outputs,e=>(o(),s("div",{key:e.id,class:"flex"},[t("div",P,n(e.manufacturer),1),t("div",q,n(e.name),1)]))),128))]))])])])],2)]),t("div",G,[t("button",{ref:"btnRef",onClick:l[0]||(l[0]=e=>d.tooltip=!d.tooltip),class:"rounded-lg bg-green-800 px-2 py-1 text-white shadow hover:text-yellow-200 hover:shadow-lg",type:"button"},U,512)])]),t("div",W,[H,t("table",L,[R,t("tbody",Y,[d.events.length===0?(o(),s("tr",j,K)):m("",!0),(o(!0),s(c,null,h(d.events,(e,p)=>(o(),s("tr",{key:p},[t("td",Q,n(e.timeStamp.toFixed(2)),1),t("td",X,n(e.data[0]),1),t("td",Z,n(e.data[0]|i.midiCommand),1),t("td",$,n(e.data[1]),1),e.data[0]===144||e.data[0]==128?(o(),s("td",tt,n(e.data[1]|i.midiNote),1)):(o(),s("td",et,"-")),t("td",st,n(e.data[2]),1),t("td",ot,n(e.srcElement.name),1)]))),128))])])])]))])}const lt=u(v,[["render",it]]);export{lt as default}; diff --git a/_nuxt/BvT8JnCb.js b/_nuxt/DJOb4bXW.js similarity index 65% rename from _nuxt/BvT8JnCb.js rename to _nuxt/DJOb4bXW.js index 8c0ef24b..e5078700 100644 --- a/_nuxt/BvT8JnCb.js +++ b/_nuxt/DJOb4bXW.js @@ -1 +1 @@ -import{m as o,o as r,c as t,a8 as s}from"./CZZfhpmp.js";const c={};function n(e,a){return r(),t("tbody",null,[s(e.$slots,"default")])}const d=o(c,[["render",n]]);export{d as default}; +import{m as o,o as r,c as t,a8 as s}from"./K1dcBiIN.js";const c={};function n(e,a){return r(),t("tbody",null,[s(e.$slots,"default")])}const d=o(c,[["render",n]]);export{d as default}; diff --git a/_nuxt/DKixc0ER.js b/_nuxt/DKixc0ER.js deleted file mode 100644 index 74af8362..00000000 --- a/_nuxt/DKixc0ER.js +++ /dev/null @@ -1 +0,0 @@ -import{a as o}from"./BNTwU45X.js";import{m as c,c as n,i as t,o as a}from"./CZZfhpmp.js";const r={};function s(_,m){const e=o;return a(),n("div",null,[t(e,{showImages:""})])}const d=c(r,[["render",s]]);export{d as default}; diff --git a/_nuxt/DMa1cH9I.js b/_nuxt/DMa1cH9I.js deleted file mode 100644 index b795b340..00000000 --- a/_nuxt/DMa1cH9I.js +++ /dev/null @@ -1 +0,0 @@ -import{c as s,b as e,F as c,r as h,o,t as a}from"./CZZfhpmp.js";const u={class:"container mx-auto font-mono text-white"},p={class:"grid grid-cols-10 gap-y-6"},_={class:"col-span-2"},m={class:"col-span-8"},v={class:"flex-col space-y-2"},f={class:"text-orange-500"},g={class:"flex"},b=["href"],x=["href"],D={__name:"talks",setup(w){const d=[{title:"Dagster Deep Dive",subtitle:"Data Quality: Building Reliable Data Platforms",date:new Date(2024,8,6),href:"https://github.com/dagster-io/talks/blob/main/slides/deep-dive-data-quality.pdf",video_href:"https://www.youtube.com/watch?v=vT0sSKEPE3A"},{title:"MotherDuck and Dagster",subtitle:"From local development to production",date:new Date(2024,4,18),href:"https://github.com/dagster-io/talks/blob/main/slides/motherduck-dagster-evidence-hybrid-compute.pdf",video_href:"https://www.youtube.com/watch?v=cOSiMMb_rjk"},{title:"Dagster Deep Dive",subtitle:"Configurations and Resources",date:new Date(2024,3,5),href:"https://github.com/dagster-io/talks/blob/main/slides/02-deep-dive-resources.pdf",video_href:"https://www.youtube.com/watch?v=i6m7k16W-yg"}],n=function(i){return i.toLocaleDateString("en-US",{month:"short",day:"2-digit",year:"numeric"})};return(i,r)=>(o(),s("div",u,[r[0]||(r[0]=e("h1",{class:"my-6 text-2xl font-extrabold"},"Talks",-1)),e("div",p,[(o(),s(c,null,h(d,(t,l)=>(o(),s(c,{key:l},[e("div",_,a(n(t.date)),1),e("div",m,[e("div",v,[e("div",f,a(t.title),1),e("div",null,a(t.subtitle),1),e("div",g,[e("a",{class:"text-xs uppercase text-gray-400 hover:cursor-pointer hover:text-orange-500",href:t.href}," [slides] ",8,b),e("a",{class:"text-xs uppercase text-gray-400 hover:cursor-pointer hover:text-orange-500",href:t.video_href}," [video] ",8,x)])])])],64))),64))])]))}};export{D as default}; diff --git a/_nuxt/DOZLo8mA.js b/_nuxt/DOZLo8mA.js new file mode 100644 index 00000000..c8de01f5 --- /dev/null +++ b/_nuxt/DOZLo8mA.js @@ -0,0 +1 @@ +import{a as o}from"./Bildd8lj.js";import{m as c,c as n,i as t,o as a}from"./K1dcBiIN.js";const r={};function s(_,m){const e=o;return a(),n("div",null,[t(e,{showImages:""})])}const d=c(r,[["render",s]]);export{d as default}; diff --git a/_nuxt/DP6TDZ8u.js b/_nuxt/DP6TDZ8u.js new file mode 100644 index 00000000..0458eeb8 --- /dev/null +++ b/_nuxt/DP6TDZ8u.js @@ -0,0 +1 @@ +import{d as c,I as i,k as p,o as s,c as t,a as u,a8 as n}from"./K1dcBiIN.js";const f=["id"],l=["href"],k=c({__name:"ProseH1",props:{id:{}},setup(a){const r=a,{headings:o}=i().public.mdc,d=p(()=>{var e;return r.id&&((e=o==null?void 0:o.anchorLinks)==null?void 0:e.h1)});return(e,m)=>(s(),t("h1",{id:e.id},[u(d)?(s(),t("a",{key:0,href:`#${e.id}`},[n(e.$slots,"default")],8,l)):n(e.$slots,"default",{key:1})],8,f))}});export{k as default}; diff --git a/_nuxt/DS2wgvBY.js b/_nuxt/DS2wgvBY.js deleted file mode 100644 index e2ef1322..00000000 --- a/_nuxt/DS2wgvBY.js +++ /dev/null @@ -1 +0,0 @@ -import{k as C,z as g,A as E,B as O,d as R,j as N,w as U,v as V,o as n,c as l,b as o,a as r,F as m,C as q,D as I,E as K,r as k,g as B,t as x,h as S}from"./CZZfhpmp.js";import{h as W}from"./DvDH6DOc.js";import{u as M}from"./BT7WDeVb.js";function G(v,c,p){const[e={},i]=typeof c=="string"?[{},c]:[c,p],s=C(()=>g(v)),t=e.key||W([i,typeof s.value=="string"?s.value:"",...H(e)]);if(!t||typeof t!="string")throw new TypeError("[nuxt] [useFetch] key must be a string: "+t);const f=t===i?"$f"+t:t;if(!e.baseURL&&typeof s.value=="string"&&s.value[0]==="/"&&s.value[1]==="/")throw new Error('[nuxt] [useFetch] the request URL must not start with "//".');const{server:w,lazy:_,default:j,transform:D,pick:F,watch:d,immediate:a,getCachedData:u,deep:y,dedupe:L,...$}=e,b=E({...O,...$,cache:typeof e.cache=="boolean"?void 0:e.cache}),A={server:w,lazy:_,default:j,transform:D,pick:F,immediate:a,getCachedData:u,deep:y,dedupe:L,watch:d===!1?[]:[b,s,...d||[]]};let h;return M(f,()=>{var z;(z=h==null?void 0:h.abort)==null||z.call(h),h=typeof AbortController<"u"?new AbortController:{};const T=g(e.timeout);return T&&setTimeout(()=>h.abort(),T),(e.$fetch||globalThis.$fetch)(s.value,{signal:h.signal,...b})},A)}function H(v){var p;const c=[((p=g(v.method))==null?void 0:p.toUpperCase())||"GET",g(v.baseURL)];for(const e of[v.params||v.query]){const i=g(e);if(!i)continue;const s={};for(const[t,f]of Object.entries(i))s[g(t)]=g(f);c.push(s)}return c}const P={class:"flex h-screen flex-col font-mono"},Q={class:"flex flex-1 overflow-hidden"},J={class:"flex flex-1 flex-col overflow-y-auto bg-amber-100 p-8"},X={class:"inline-flex flex-col justify-center py-4 text-gray-600"},Y={key:0,class:"mt-2 w-full border border-gray-100 bg-white"},Z=["onClick"],ee={class:"flex p-4"},te={class:"text-cyan-600 flex-1 text-center text-3xl font-bold"},oe={class:"text-amber-500"},se={class:"grid grid-cols-1 gap-8 md:grid-cols-3 xl:grid-cols-4 xl:gap-12"},ae={class:"border-cyan-600 h-full space-y-3 rounded-md border-2 bg-white p-4 shadow shadow-amber-500"},re={class:"text-2xl font-semibold capitalize text-gray-700"},ne={class:"text-gray-500"},le={key:1,class:"italic"},he=R({__name:"index",async setup(v){let c,p;const e=N(0),i=N(""),s=N([]),{data:t}=([c,p]=U(()=>G("/1000_french_conjugations.json",{transform:d=>d},"$lRKQKt9Al2")),c=await c,p(),c),f=C(()=>{if(t.value)return t.value[e.value]}),w=C(()=>{if(t.value!==null)return e.value===0?void 0:t.value[e.value-1]}),_=C(()=>{if(t.value!==null)return e.value+1===t.value.length?void 0:t.value[e.value+1]});V(i,d=>{if(s.value=[],!d)return;let a=0;s.value=t.value.filter(u=>u.word.normalize("NFD").replace(new RegExp("\\p{Diacritic}","gu"),"").includes(d)&&a<=5?(a++,!0):!1)});const j=()=>{t.value&&e.value{e.value>0&&(e.value-=1)},F=d=>{i.value="",s.value=[],e.value=d.word_popularity-1};return(d,a)=>(n(),l("div",P,[o("div",Q,[a[3]||(a[3]=o("div",{class:"flex w-20 bg-amber-500"},[o("div",{class:"absolute bottom-10 w-20 -rotate-90 transform whitespace-nowrap"},[o("div",{class:"text-4xl font-bold text-white"}," 1000 French Conjugations ")])],-1)),o("div",J,[r(t)&&r(t).length>0&&r(f)?(n(),l(m,{key:0},[a[2]||(a[2]=o("div",{class:"flex rounded-xl bg-amber-500 p-4"},[o("div",{class:"text-center text-xl italic text-white"}," Click a word to the left or right to cycle through the 1000 most popular French verb conjugations! ")],-1)),o("div",X,[q(o("input",{"onUpdate:modelValue":a[0]||(a[0]=u=>K(i)?i.value=u:null),class:"rounded-xl border border-2 border-gray-400 p-2 pl-8 focus:border-amber-500 focus:outline-none",type:"search",autocomplete:"off",placeholder:"Search Words"},null,512),[[I,r(i)]]),r(s).length>0?(n(),l("ul",Y,[(n(!0),l(m,null,k(r(s),u=>(n(),l("li",{key:u.word,class:"relative cursor-pointer py-1 pl-8 pr-2 hover:bg-yellow-50 hover:text-gray-900",onClick:y=>F(u)},[a[1]||(a[1]=o("svg",{class:"absolute left-2 top-2 h-4 w-4",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor"},[o("path",{d:"M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z"})],-1)),B(" "+x(u.word),1)],8,Z))),128))])):S("",!0)]),o("div",ee,[o("div",{class:"flex-1 cursor-pointer select-none text-center text-2xl text-gray-400",onClick:D},x(r(w)?r(w).word:"-"),1),o("div",te,[o("span",oe," #"+x(r(f).word_popularity),1),B(" "+x(r(f).word),1)]),o("div",{class:"flex-1 cursor-pointer select-none text-center text-2xl text-gray-400",onClick:j},x(r(_)?r(_).word:"-"),1)]),o("div",se,[(n(!0),l(m,null,k(r(f).conjugations,(u,y)=>(n(),l("div",{key:y},[o("div",ae,[o("h1",re,x(y),1),o("div",ne,[(n(!0),l(m,null,k(u,(L,$)=>(n(),l("p",{key:$},[(n(!0),l(m,null,k(L,(b,A)=>(n(),l("i",{key:A},x(b.text),1))),128))]))),128))])])]))),128))])],64)):(n(),l("div",le,"Loading..."))])])]))}});export{he as default}; diff --git a/_nuxt/DV8CRu_y.js b/_nuxt/DV8CRu_y.js deleted file mode 100644 index bc35546c..00000000 --- a/_nuxt/DV8CRu_y.js +++ /dev/null @@ -1 +0,0 @@ -import{d as N,u as R,w as g,n as B,a as o,o as r,c,b as e,F as f,r as h,e as v,f as m,g as b,t as _,h as y,i as w,_ as T}from"./CZZfhpmp.js";import{_ as V}from"./CuOPeUWs.js";import $ from"./B1tmNyhF.js";import{u as D}from"./BT7WDeVb.js";import{q as E}from"./CmpoAw97.js";import"./C-v3KzvZ.js";import"./Dnd51l0P.js";import"./B2jTtLqC.js";import"./DvDH6DOc.js";const q={key:0,class:"container mx-auto"},A={class:"mb-10 bg-gray-200 p-10 shadow-lg"},F={class:"space-y-6"},L={class:"flex space-x-2"},S={class:"flex flex-col space-y-2 md:flex md:flex-row md:space-x-2 md:space-y-0"},I={class:"flex flex-col space-y-2 md:flex md:flex-row md:space-x-2 md:space-y-0"},M={class:"flex"},O=["src"],j={class:"text-xl font-bold text-gray-700 md:text-3xl"},z={class:"prose max-w-none prose-a:font-bold prose-a:no-underline hover:prose-a:text-orange-500 prose-pre:bg-white prose-pre:text-black"},Z=N({__name:"[...slug]",async setup(G){let s,l;const d=R(),{data:t}=([s,l]=g(()=>D("page-data",()=>E(d.path).findOne())),s=await s,l(),s),u={};if(t.value===null||d.path in u){const i=u[d.path]||"/";console.log(i),[s,l]=g(()=>B({path:i})),await s,l()}return(i,a)=>{const x=T,k=V,C=$;return o(t)?(r(),c("div",q,[e("article",A,[e("div",F,[e("div",L,[e("div",null,[a[0]||(a[0]=e("div",{class:"text-xs uppercase text-gray-400"},"Category",-1)),e("div",S,[(r(!0),c(f,null,h(o(t).categories,(n,p)=>(r(),v(x,{class:"w-min rounded-md bg-background px-2 text-sm font-bold text-white hover:cursor-pointer hover:bg-orange-500",key:p,to:`/articles?category=${n}`},{default:m(()=>[b(_(n),1)]),_:2},1032,["to"]))),128))])]),a[2]||(a[2]=e("div",{class:"border-r border-gray-400"},null,-1)),e("div",null,[a[1]||(a[1]=e("div",{class:"text-xs uppercase text-gray-400"},"Tags",-1)),e("div",I,[(r(!0),c(f,null,h(o(t).tags,(n,p)=>(r(),v(x,{class:"w-min rounded-md bg-background px-2 text-sm font-bold text-white hover:cursor-pointer hover:bg-orange-500",key:p,to:`/articles?tag=${n}`},{default:m(()=>[b(_(n),1)]),_:2},1032,["to"]))),128))])])]),e("div",M,[o(t).cover_image?(r(),c("img",{key:0,class:"mr-4 h-16 border-2 border-black",src:o(t).cover_image},null,8,O)):y("",!0),e("h1",j,_(o(t).title),1)])]),e("article",z,[w(C,null,{default:m(()=>[w(k,{value:o(t)},null,8,["value"])]),_:1})])])])):y("",!0)}}});export{Z as default}; diff --git a/_nuxt/DYh1WRot.js b/_nuxt/DYh1WRot.js deleted file mode 100644 index a1836290..00000000 --- a/_nuxt/DYh1WRot.js +++ /dev/null @@ -1 +0,0 @@ -import{m as v,c as r,g as l,b as e,l as b,t as d,F as c,r as u,i as _,f as y,T as M,o as n,h as g}from"./CZZfhpmp.js";var p={};Object.defineProperty(p,"__esModule",{value:!0});var h=p.identify=void 0;const O=["C","C# / Db","D","D# / Eb","E","F","F# / Gb","G","G# / Ab","A","A# / Bb","B"],x={"0 1":{name:"No 3 Major 7",rootOffset:1},"0 2":{name:"No 3 7",rootOffset:2},"0 3":{name:"Minor",rootOffset:0},"0 4":{name:"",rootOffset:0},"0 5":{name:"5",rootOffset:5},"0 6":{name:"7",rootOffset:2},"0 7":{name:"5",rootOffset:0},"0 8":{name:"",rootOffset:8},"0 9":{name:"Minor",rootOffset:9},"0 10":{name:"No 3 7",rootOffset:0},"0 11":{name:"No 3 Major 7",rootOffset:0},"0 2 7":{name:"Suspended 2",rootOffset:0},"0 3 6 10":{name:"Half-diminished 7",rootOffset:0},"0 3 6 9":{name:"Diminished 7",rootOffset:0},"0 3 6":{name:"Diminished",rootOffset:0},"0 3 7 10":{name:"Minor 7",rootOffset:0},"0 3 7 11":{name:"Minor-major 7",rootOffset:0},"0 3 7 9":{name:"Minor 6",rootOffset:0},"0 3 7":{name:"Minor",rootOffset:0},"0 4 10":{name:"7",rootOffset:0},"0 4 11":{name:"Major 7",rootOffset:0},"0 4 5 7":{name:"Add 11",rootOffset:0},"0 4 6":{name:"Flat 5",rootOffset:0},"0 4 7 10":{name:"Dominant 7",rootOffset:0},"0 4 7 11":{name:"Major 7",rootOffset:0},"0 4 7 9":{name:"Major 6",rootOffset:0},"0 4 7":{name:"",rootOffset:0},"0 4 8 10":{name:"Augmented 7",rootOffset:0},"0 4 8":{name:"Augmented",rootOffset:0},"0 5 7":{name:"Suspended 4",rootOffset:0},"0 5 8":{name:"Minor",rootOffset:5},"0 5 9":{name:"",rootOffset:5},"0 4 9":{name:"Minor",rootOffset:9},"0 3 8":{name:"",rootOffset:8},"0 1 5":{name:"Major 7",rootOffset:1},"0 2 6":{name:"Major 7",rootOffset:2},"0 4 5":{name:"5 Major 7",rootOffset:5},"0 1 2":{name:"No 3 7 Major 7",rootOffset:2},"0 1 3":{name:"Minor Add Flat 9",rootOffset:0},"0 1 6":{name:"5 Sharp 11",rootOffset:6},"0 1 7":{name:"5 Add Flat 9",rootOffset:0},"0 1 8":{name:"5 Major 7",rootOffset:1},"0 1 9":{name:"Sharp 9",rootOffset:9},"0 1 10":{name:"Minor Add 9",rootOffset:10},"0 1 11":{name:"No 3 7 Major 7",rootOffset:1},"0 2 10":{name:"Add 9",rootOffset:10},"0 2 11":{name:"Minor Add Flat 9",rootOffset:11},"0 2 3":{name:"Minor Add 9",rootOffset:0},"0 2 4":{name:"Add 9",rootOffset:0},"0 2 5":{name:"Minor 7",rootOffset:2},"0 2 8":{name:"Flat 5",rootOffset:8},"0 2 9":{name:"5 7",rootOffset:2},"0 3 10":{name:"Minor 7",rootOffset:0},"0 3 4":{name:"Sharp 9",rootOffset:0},"0 3 5":{name:"5 7",rootOffset:5},"0 3 9":{name:"Minor 6",rootOffset:0},"0 5 10":{name:"Suspended 2",rootOffset:10},"0 5 11":{name:"5 Sharp 11",rootOffset:5},"0 5 6":{name:"5 Add Flat 9",rootOffset:5},"0 6 10":{name:"Flat 5",rootOffset:6},"0 6 7":{name:"5 Sharp 11",rootOffset:0},"0 6 8":{name:"7",rootOffset:8},"0 6 9":{name:"Minor 6",rootOffset:9},"0 7 10":{name:"5 7",rootOffset:0},"0 7 11":{name:"5 Major 7",rootOffset:0},"0 7 8":{name:"Major 7",rootOffset:8},"0 7 9":{name:"Minor 7",rootOffset:9},"0 8 10":{name:"Add 9",rootOffset:8},"0 8 11":{name:"Sharp 9",rootOffset:8},"0 9 10":{name:"Minor Add Flat 9",rootOffset:9},"0 9 11":{name:"Minor Add 9",rootOffset:9},"0 10 11":{name:"No 3 7 Major 7",rootOffset:0},"0 1 4":{name:"Sharp 9",rootOffset:9},"0 8 9":{name:"Sharp 9",rootOffset:5},"0 6 11":{name:"7/13",rootOffset:2},"0 3 11":{name:"Sharp 9",rootOffset:8}};function w(i){const o=i.map(t=>typeof t=="number"?t:O.indexOf(t));if(o.some(t=>t<0))throw new Error("Unsupported note letter or number provided");if(new Set(o.map(t=>t%12)).size===1)return{name:O[o[0]%12]};const f=o.sort((t,s)=>t-s)[0]%12,m=[...new Set(o.map(t=>(t-f)%12).sort((t,s)=>t-s))],a=x[m.join(" ")];if(a){const t=(f+a.rootOffset)%12,s=O[t];return{name:a.name!==""?`${s} ${a.name}`:s,interval:m,root:t}}else return{name:void 0}}h=p.identify=w;const A={mounted(){typeof navigator.requestMIDIAccess<"u"&&navigator.requestMIDIAccess().then(i=>{this.midi=i,this.midi.inputs.forEach(o=>{o.onmidimessage=f=>{f.data[0]===144&&(this.activeKeys.set(f.data[1],f.data),this.$forceUpdate()),f.data[0]===128&&(this.activeKeys.delete(f.data[1]),this.$forceUpdate())}})},i=>{console.error(i)})},data(){return{tooltip:!1,midi:void 0,activeKeys:new Map}},computed:{inputs(){if(typeof this.midi<"u")return Array.from(this.midi.inputs.values())},outputs(){if(typeof this.midi<"u")return Array.from(this.midi.outputs.values())}},methods:{orderedNotes(){return Array.from(this.activeKeys.keys()).sort()},chord(){const i=Array.from(this.activeKeys.keys());return h(i).name}}},k={class:"h-2/3 bg-gradient-to-b from-green-900 via-purple-900 to-indigo-900 text-white"},N={key:0,class:"p-4 text-center font-light tracking-wide"},S={key:1},j={class:"flex flex-wrap"},I={class:"absolute bottom-16 right-2"},D={class:"p-3 font-mono text-orange-900"},F={class:"mb-2 font-bold"},E={class:"mb-2"},z={key:0,class:"p-4 text-center italic"},V={key:1},C={class:"flex-1"},B={class:"flex-1"},K={class:"mb-2"},T={key:0,class:"p-4 text-center italic"},P={key:1},U={class:"flex-1"},G={class:"flex-1"},L={class:"absolute bottom-2 right-2"},q={class:"absolute bottom-4 left-4"},H={class:"flex"},R={class:"grid h-screen place-items-center"},W={class:"text-center text-4xl font-semibold tracking-wide"},Y={key:0};function J(i,o,f,m,a,t){return n(),r("div",k,[typeof a.midi>"u"?(n(),r("div",N,o[1]||(o[1]=[l(" Unfortunately, the Web MIDI API is "),e("a",{class:"text-blue-500 underline",href:"https://developer.mozilla.org/en-US/docs/Web/API/MIDIMessageEvent#browser_compatibility"},"not supported",-1),l(" in all browsers... ")]))):(n(),r("div",S,[e("div",j,[e("div",I,[e("div",{class:b([{hidden:!a.tooltip,block:a.tooltip},"z-50 max-w-md break-words rounded-lg border-2 border-green-800 bg-yellow-200 text-sm font-normal leading-normal"])},[e("div",null,[o[5]||(o[5]=e("div",{class:"mb-0 rounded-t-lg border-b border-solid bg-green-600 p-3 font-semibold uppercase text-white opacity-75"}," MIDI Status ",-1)),e("div",D,[e("div",F,[o[2]||(o[2]=l(" Enabled: ")),e("span",null,d(typeof a.midi<"u"?"Yep!":"Nope"),1)]),e("div",E,[o[3]||(o[3]=e("div",{class:"font-bold"},"Inputs:",-1)),t.inputs.length===0?(n(),r("div",z," No input devices detected :( ")):(n(),r("div",V,[(n(!0),r(c,null,u(t.inputs,s=>(n(),r("div",{key:s.id,class:"flex"},[e("div",C,d(s.manufacturer),1),e("div",B,d(s.name),1)]))),128))]))]),e("div",K,[o[4]||(o[4]=e("div",{class:"font-bold"},"Outputs:",-1)),t.outputs.length===0?(n(),r("div",T," No output devices detected :( ")):(n(),r("div",P,[(n(!0),r(c,null,u(t.outputs,s=>(n(),r("div",{key:s.id,class:"flex"},[e("div",U,d(s.manufacturer),1),e("div",G,d(s.name),1)]))),128))]))])])])],2)]),e("div",L,[e("button",{onClick:o[0]||(o[0]=s=>a.tooltip=!a.tooltip),class:"border-3 rounded-lg border-green-600 bg-green-50 px-1 text-green-600 shadow hover:text-green-500 hover:shadow-lg",type:"button"},o[6]||(o[6]=[e("svg",{xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 20 20",class:"h-10 w-10"},[e("g",{fill:"none"},[e("path",{d:"M2.5 4a.5.5 0 0 0-.5.5v11a.5.5 0 0 0 .5.5h15a.5.5 0 0 0 .5-.5v-11a.5.5 0 0 0-.5-.5h-15zm.5 6h2v3.5a.5.5 0 0 0 1 0V10h2v3.5a.5.5 0 0 0 1 0V10h2v3.5a.5.5 0 0 0 1 0V10h2v3.5a.5.5 0 0 0 1 0V10h2v5H3v-5zm2.75-2.5a.75.75 0 1 1 0-1.5a.75.75 0 0 1 0 1.5zm6.25-1a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5zm-3 .251a.75.75 0 1 1-1.5 0a.75.75 0 0 1 1.5 0z",fill:"currentColor"})])],-1)]))])]),e("div",q,[e("div",H,[(n(!0),r(c,null,u(t.orderedNotes(),s=>(n(),r("div",{key:s,class:"p-4"},d(s),1))),128))])]),e("div",R,[e("div",null,[e("div",W,[_(M,{"enter-active-class":"duration-500 ease-out","enter-class":"opacity-0 transform","enter-to-class":"opacity-100","leave-active-class":"duration-500","leave-class":"opacity-100","leave-to-class":"opacity-0 transform"},{default:y(()=>[a.activeKeys.size>=1?(n(),r("div",Y,d(t.chord()||"?"),1)):g("",!0)]),_:1})])])])]))])}const X=v(A,[["render",J]]);export{X as default}; diff --git a/_nuxt/Dab_E90i.js b/_nuxt/Dab_E90i.js deleted file mode 100644 index 7caddf27..00000000 --- a/_nuxt/Dab_E90i.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as m}from"./CZYXMW8W.js";import"./CZZfhpmp.js";export{m as default}; diff --git a/_nuxt/LT2DbrHy.js b/_nuxt/DbroGl9h.js similarity index 56% rename from _nuxt/LT2DbrHy.js rename to _nuxt/DbroGl9h.js index 1b04d834..582312fe 100644 --- a/_nuxt/LT2DbrHy.js +++ b/_nuxt/DbroGl9h.js @@ -1 +1 @@ -import{m as r,a8 as t}from"./CZZfhpmp.js";const s={};function n(e,o){return t(e.$slots,"default")}const c=r(s,[["render",n]]);export{c as default}; +import{m as r,a8 as t}from"./K1dcBiIN.js";const s={};function n(e,o){return t(e.$slots,"default")}const c=r(s,[["render",n]]);export{c as default}; diff --git a/_nuxt/BacZaOvF.js b/_nuxt/DcLi_FTb.js similarity index 63% rename from _nuxt/BacZaOvF.js rename to _nuxt/DcLi_FTb.js index e0fcd996..19013149 100644 --- a/_nuxt/BacZaOvF.js +++ b/_nuxt/DcLi_FTb.js @@ -1 +1 @@ -import{d as a,o as n,e as o,f as s,a8 as f,_ as u}from"./CZZfhpmp.js";const d=a({__name:"ProseA",props:{href:{type:String,default:""},target:{type:String,default:void 0,required:!1}},setup(e){return(t,_)=>{const r=u;return n(),o(r,{href:e.href,target:e.target},{default:s(()=>[f(t.$slots,"default")]),_:3},8,["href","target"])}}});export{d as default}; +import{d as a,o as n,e as o,f as s,a8 as f,_ as u}from"./K1dcBiIN.js";const d=a({__name:"ProseA",props:{href:{type:String,default:""},target:{type:String,default:void 0,required:!1}},setup(e){return(t,_)=>{const r=u;return n(),o(r,{href:e.href,target:e.target},{default:s(()=>[f(t.$slots,"default")]),_:3},8,["href","target"])}}});export{d as default}; diff --git a/_nuxt/Ddr6mL0e.js b/_nuxt/Ddr6mL0e.js deleted file mode 100644 index 3d8ff76c..00000000 --- a/_nuxt/Ddr6mL0e.js +++ /dev/null @@ -1 +0,0 @@ -import{q,v as D,x as T,o as b,c as p,b as t,d as E,j as W,y as R,i as C,a as _,F as A,r as F,t as h}from"./CZZfhpmp.js";const M={id:"waveform-canvas-container",class:"bg-green h-full w-full"},N=["width","height"],P={__name:"Waveform",props:{timeDomainBufferHistory:{type:Array},canvasWidth:{type:Number},canvasHeight:{type:Number},fillStyle:{type:String,default:"rgba(0,0,0)"},strokeStyle:{type:String,default:"rgb(255, 255, 255)"}},setup(f){const l=f;return q(()=>{const d=document.getElementById("waveformCanvas2"),e=d.getContext("2d"),s=document.getElementById("waveform-canvas-container"),c=l.canvasHeight?l.canvasHeight:s.clientHeight,o=l.canvasWidth?l.canvasWidth:s.clientWidth;d.height=c,d.width=o,e.fillRect(0,0,o,c),D(l.timeDomainBufferHistory,a=>{e.fillStyle=l.fillStyle,e.fillRect(0,0,o,c),e.lineWidth=2,e.strokeStyle=l.strokeStyle,e.beginPath();const u=a.slice(-1)[0],v=u.length,m=o/v;let g=0;for(let i=0;i{}),(d,e)=>(b(),p("div",M,[t("canvas",{id:"waveformCanvas2",width:f.canvasWidth,height:f.canvasHeight},null,8,N)]))}},U={id:"spectrogram-canvas-container",class:"h-full w-full"},O=["width","height"],k=36,G={__name:"Spectrogram",props:{frequencyDomainBufferHistory:{type:Array},canvasWidth:{type:Number},canvasHeight:{type:Number},fillStyle:{type:String,default:"rgba(0,0,0)"}},setup(f){const l=f,d=(e,s,c,o,a)=>(e-s)*(a-s)/(c-s)+o;return q(()=>{const e=document.getElementById("spectrogramCanvas"),s=e.getContext("2d"),c=document.getElementById("spectrogram-canvas-container"),o=l.canvasHeight?l.canvasHeight:c.clientHeight,a=l.canvasWidth?l.canvasWidth:c.clientWidth;e.height=o,e.width=a,s.fillRect(0,0,a,o),D(l.frequencyDomainBufferHistory,u=>{s.fillStyle=l.fillStyle,s.fillRect(0,0,a,o);const v=u.slice(-k),m=a/128,g=o/k;for(let i=0;i<128;i++)for(let n=0;n(b(),p("div",null,[t("div",U,[t("canvas",{id:"spectrogramCanvas",width:f.canvasWidth,height:f.canvasHeight},null,8,O)])]))}},L={id:"bar-graph-container",class:"h-full w-full"},V=["width","height"],I=2,Y={__name:"FrequencyBarGraph",props:{audioBufferHistory:{type:Array},canvasWidth:{type:Number},canvasHeight:{type:Number},fillStyle:{type:String,default:"rgba(0,0,0)"},strokeStyle:{type:String,default:"rgb(255, 255, 255)"}},setup(f){const l=f,d=(e,s,c,o,a)=>(e-s)*(a-s)/(c-s)+o;return q(()=>{const e=document.getElementById("frequencyBarGraphCanvas"),s=e.getContext("2d"),c=document.getElementById("bar-graph-container"),o=l.canvasHeight?l.canvasHeight:c.clientHeight,a=l.canvasWidth?l.canvasWidth:c.clientWidth;e.height=o,e.width=a,s.fillRect(0,0,a,o),D(l.audioBufferHistory,u=>{s.fillStyle=l.fillStyle,s.fillRect(0,0,a,o);const v=u.slice(-1)[0],m=a/v.length-I;let g=0;for(let i=0;i(b(),p("div",null,[t("div",L,[t("canvas",{id:"frequencyBarGraphCanvas",width:f.canvasWidth,height:f.canvasHeight},null,8,V)])]))}},j={class:"container mx-auto font-mono"},z={class:"bg-background text-white"},K={class:"grid grid-cols-3 gap-4"},X={class:"col-span-3 rounded-xl bg-black/75 p-4 lg:col-span-1"},Z={class:"col-span-3 rounded-xl bg-black/75 p-4 lg:col-span-1"},J={class:"col-span-3 rounded-xl bg-black/75 p-4 lg:col-span-1"},Q={class:"col-span-3 rounded-xl bg-black/75 p-4"},tt={class:"w-full table-fixed"},et={class:"text-left font-bold"},nt={class:"text-left"},st={class:"text-left"},lt={class:"text-left"},ot={class:"text-left"},at={class:"truncate text-right"},it={class:"col-span-3 rounded-xl bg-black/75 p-4"},ct={class:"w-full table-fixed"},rt={class:"text-left font-bold"},dt={class:"text-left"},ut={class:"text-left"},ht={class:"text-left"},ft={class:"text-left"},gt={class:"truncate text-right"},B=256,yt=E({__name:"index",setup(f){let l=null,d=null,e=null,s=null,c=null,o=W([]),a=null,u=W([]);W(!1);const v=()=>{requestAnimationFrame(v),e.getByteTimeDomainData(c),c!==null&&(o.value.push(c.slice()),o.value.length>B&&o.value.shift()),e.getByteFrequencyData(a),a!==null&&(u.value.push(a.slice()),u.value.length>B&&u.value.shift())},m=()=>{navigator.mediaDevices.getUserMedia({audio:!0}).then(i=>{l=i,d=new(window.AudioContext||window.webkitAudioContext),e=d.createAnalyser(),s=d.createMediaStreamSource(l),s.connect(e),e.fftSize=2048,c=new Uint8Array(e.frequencyBinCount),a=new Uint8Array(e.frequencyBinCount);for(let n=0;n{l!==null&&l.active&&l.getAudioTracks().forEach(i=>{i.stop()})};return R(()=>{console.log("disabling"),g()}),(i,n)=>{const y=P,w=G,$=Y;return b(),p("div",j,[t("div",z,[t("div",K,[t("div",{class:"col-span-3 space-x-2"},[t("div",{class:"inline-block rounded-lg bg-black px-6 py-2 text-sm font-bold uppercase text-white shadow-lg shadow-green-400/25 transition duration-150 ease-in-out hover:cursor-pointer hover:shadow-white/25",onClick:m}," Enable "),t("div",{class:"inline-block rounded-lg bg-black px-6 py-2 text-sm font-bold uppercase text-white shadow-lg shadow-red-400/25 transition duration-150 ease-in-out hover:cursor-pointer hover:shadow-white/25",onClick:g}," Disable ")]),t("div",X,[n[0]||(n[0]=t("div",{class:"mb-2 text-xl font-bold"},"Time Domain Waveform",-1)),C(y,{timeDomainBufferHistory:_(o),strokeStyle:"rgb(255, 0, 255)",class:"h-72 border-2 border-gray-400"},null,8,["timeDomainBufferHistory"])]),t("div",Z,[n[1]||(n[1]=t("div",{class:"mb-2 text-xl font-bold"},"Frequency Spectrogram",-1)),C(w,{frequencyDomainBufferHistory:_(u),class:"h-72 border-2 border-gray-400"},null,8,["frequencyDomainBufferHistory"])]),t("div",J,[n[2]||(n[2]=t("div",{class:"mb-2 text-xl font-bold"},"Frequency Bar Chart",-1)),C($,{audioBufferHistory:_(u),class:"h-72 border-2 border-gray-400"},null,8,["audioBufferHistory"])]),t("div",Q,[n[4]||(n[4]=t("div",{class:"mb-2 text-xl font-bold"},"Frequency Buffer History",-1)),t("div",null,[t("table",tt,[n[3]||(n[3]=t("thead",{class:"collapse border-b-2 md:visible"},[t("tr",null,[t("th",{class:"text-left"},"Index"),t("th",{class:"text-left"},"Mean"),t("th",{class:"text-left"},"Min"),t("th",{class:"text-left"},"Max"),t("th",{class:"text-left"},"FFT"),t("th",{class:"text-right"},"Buffer")])],-1)),t("tbody",null,[(b(!0),p(A,null,F(_(u).slice(-10),(r,x)=>(b(),p("tr",{key:x},[t("td",et,h(x),1),t("td",nt,h((r.reduce((H,S)=>H+S)/r.length).toFixed(2)),1),t("td",st,h(Math.min(...r)),1),t("td",lt,h(Math.max(...r)),1),t("td",ot,h(r.length),1),t("td",at,h(r.slice(0,4))+" ... "+h(r.slice(-4)),1)]))),128))])])])]),t("div",it,[n[6]||(n[6]=t("div",{class:"mb-2 text-xl font-bold"},"Time Domain Buffer History",-1)),t("div",null,[t("table",ct,[n[5]||(n[5]=t("thead",{class:"collapse border-b-2 md:visible"},[t("tr",null,[t("th",{class:"text-left"},"Index"),t("th",{class:"text-left"},"Mean"),t("th",{class:"text-left"},"Min"),t("th",{class:"text-left"},"Max"),t("th",{class:"text-left"},"FFT"),t("th",{class:"text-right"},"Buffer")])],-1)),t("tbody",null,[(b(!0),p(A,null,F(_(o).slice(-10),(r,x)=>(b(),p("tr",{key:x},[t("td",rt,h(x),1),t("td",dt,h((r.reduce((H,S)=>H+S)/r.length).toFixed(2)),1),t("td",ut,h(Math.min(...r)),1),t("td",ht,h(Math.max(...r)),1),t("td",ft,h(r.length),1),t("td",gt,h(r.slice(0,4))+" ... "+h(r.slice(-4)),1)]))),128))])])])])])])])}}});export{yt as default}; diff --git a/_nuxt/DbS0a68n.js b/_nuxt/Des7KGkR.js similarity index 77% rename from _nuxt/DbS0a68n.js rename to _nuxt/Des7KGkR.js index 1c28f326..9cf0709a 100644 --- a/_nuxt/DbS0a68n.js +++ b/_nuxt/Des7KGkR.js @@ -1 +1 @@ -import{d as n,L as e}from"./CZZfhpmp.js";const r=n({name:"DocumentDrivenEmpty",props:{value:{type:Object,required:!0}},render({value:t}){return e("div",void 0,[e("p","Document is empty"),e("p",`Add content to it by opening ${t._source}/${t._file} file.`)])}});export{r as default}; +import{d as n,L as e}from"./K1dcBiIN.js";const r=n({name:"DocumentDrivenEmpty",props:{value:{type:Object,required:!0}},render({value:t}){return e("div",void 0,[e("p","Document is empty"),e("p",`Add content to it by opening ${t._source}/${t._file} file.`)])}});export{r as default}; diff --git a/_nuxt/CeHLcfh0.js b/_nuxt/DjOkkdqj.js similarity index 72% rename from _nuxt/CeHLcfh0.js rename to _nuxt/DjOkkdqj.js index 660a6907..02cebbf3 100644 --- a/_nuxt/CeHLcfh0.js +++ b/_nuxt/DjOkkdqj.js @@ -1,2 +1,2 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./36DYiIQe.js","./CZZfhpmp.js","./CmpoAw97.js","./DvDH6DOc.js","./B2jTtLqC.js","./C-v3KzvZ.js"])))=>i.map(i=>d[i]); -import{u as m}from"./BT7WDeVb.js";import{I as v,M as l,N as d,E as g,O as y,d as h,P as _,k as w,J as C,L as p,_ as P}from"./CZZfhpmp.js";import{h as f}from"./DvDH6DOc.js";import{q as N,w as c,e as $,s as x,j as E,u as T}from"./CmpoAw97.js";import{u as j}from"./B2jTtLqC.js";const S=async t=>{const{content:e}=v().public;typeof(t==null?void 0:t.params)!="function"&&(t=N(t));const n=t.params(),o=e.experimental.stripQueryParameters?c(`/navigation/${`${f(n)}.${e.integrity}`}/${$(n)}.json`):c(`/navigation/${f(n)}.${e.integrity}.json`);if(x())return(await l(()=>import("./36DYiIQe.js"),__vite__mapDeps([0,1,2,3,4,5]),import.meta.url).then(i=>i.generateNavigation))(n);const a=await $fetch(o,{method:"GET",responseType:"json",params:e.experimental.stripQueryParameters?void 0:{_params:E(n),previewToken:j().getPreviewToken()}});if(typeof a=="string"&&a.startsWith(""))throw new Error("Not found");return a},b="$s";function D(...t){const e=typeof t[t.length-1]=="string"?t.pop():void 0;typeof t[0]!="string"&&t.unshift(e);const[n,o]=t;if(!n||typeof n!="string")throw new TypeError("[nuxt] [useState] key must be a string: "+n);if(o!==void 0&&typeof o!="function")throw new Error("[nuxt] [useState] init must be a function: "+o);const a=b+n,r=y(),i=d(r.payload.state,a);if(i.value===void 0&&o){const s=o();if(g(s))return r.payload.state[a]=s,s;i.value=s}return i}const R=h({name:"ContentNavigation",props:{query:{type:Object,required:!1,default:void 0}},async setup(t){const{query:e}=_(t),n=w(()=>{var a;return typeof((a=e.value)==null?void 0:a.params)=="function"?e.value.params():e.value});if(!n.value&&D("dd-navigation").value){const{navigation:a}=T();return{navigation:a}}const{data:o}=await m(`content-navigation-${f(n.value)}`,()=>S(n.value));return{navigation:o}},render(t){const e=C(),{navigation:n}=t,o=i=>p(P,{to:i._path},()=>i.title),a=(i,s)=>p("ul",s?{"data-level":s}:null,i.map(u=>u.children?p("li",null,[o(u),a(u.children,s+1)]):p("li",null,o(u)))),r=i=>a(i,0);return e!=null&&e.default?e.default({navigation:n,...this.$attrs}):r(n)}}),I=R;export{I as default}; +const __vite__fileDeps=["./BwID1M5A.js","./K1dcBiIN.js","./Ce34VGij.js","./DvDH6DOc.js","./NnUIAPGH.js","./C-v3KzvZ.js"],__vite__mapDeps=i=>i.map(i=>__vite__fileDeps[i]); +import{u as m}from"./C6WZwVE2.js";import{I as v,M as l,N as d,E as g,O as y,d as h,P as _,k as w,J as C,L as p,_ as P}from"./K1dcBiIN.js";import{h as f}from"./DvDH6DOc.js";import{q as N,w as c,e as $,s as x,j as E,u as T}from"./Ce34VGij.js";import{u as j}from"./NnUIAPGH.js";const S=async t=>{const{content:e}=v().public;typeof(t==null?void 0:t.params)!="function"&&(t=N(t));const n=t.params(),o=e.experimental.stripQueryParameters?c(`/navigation/${`${f(n)}.${e.integrity}`}/${$(n)}.json`):c(`/navigation/${f(n)}.${e.integrity}.json`);if(x())return(await l(()=>import("./BwID1M5A.js"),__vite__mapDeps([0,1,2,3,4,5]),import.meta.url).then(i=>i.generateNavigation))(n);const a=await $fetch(o,{method:"GET",responseType:"json",params:e.experimental.stripQueryParameters?void 0:{_params:E(n),previewToken:j().getPreviewToken()}});if(typeof a=="string"&&a.startsWith(""))throw new Error("Not found");return a},b="$s";function D(...t){const e=typeof t[t.length-1]=="string"?t.pop():void 0;typeof t[0]!="string"&&t.unshift(e);const[n,o]=t;if(!n||typeof n!="string")throw new TypeError("[nuxt] [useState] key must be a string: "+n);if(o!==void 0&&typeof o!="function")throw new Error("[nuxt] [useState] init must be a function: "+o);const a=b+n,r=y(),i=d(r.payload.state,a);if(i.value===void 0&&o){const s=o();if(g(s))return r.payload.state[a]=s,s;i.value=s}return i}const R=h({name:"ContentNavigation",props:{query:{type:Object,required:!1,default:void 0}},async setup(t){const{query:e}=_(t),n=w(()=>{var a;return typeof((a=e.value)==null?void 0:a.params)=="function"?e.value.params():e.value});if(!n.value&&D("dd-navigation").value){const{navigation:a}=T();return{navigation:a}}const{data:o}=await m(`content-navigation-${f(n.value)}`,()=>S(n.value));return{navigation:o}},render(t){const e=C(),{navigation:n}=t,o=i=>p(P,{to:i._path},()=>i.title),a=(i,s)=>p("ul",s?{"data-level":s}:null,i.map(u=>u.children?p("li",null,[o(u),a(u.children,s+1)]):p("li",null,o(u)))),r=i=>a(i,0);return e!=null&&e.default?e.default({navigation:n,...this.$attrs}):r(n)}}),I=R;export{I as default}; diff --git a/_nuxt/DwoF_sus.js b/_nuxt/DltOabO9.js similarity index 82% rename from _nuxt/DwoF_sus.js rename to _nuxt/DltOabO9.js index 8b987101..c019a9ac 100644 --- a/_nuxt/DwoF_sus.js +++ b/_nuxt/DltOabO9.js @@ -1 +1 @@ -import{_ as l}from"./CZYXMW8W.js";import{d as n,o as s,e as i,f as o,b as r,l as g,a9 as u,a8 as f}from"./CZZfhpmp.js";const h=n({__name:"ProsePre",props:{code:{type:String,default:""},language:{type:String,default:null},filename:{type:String,default:null},highlights:{type:Array,default:()=>[]},meta:{type:String,default:null},class:{type:String,default:null},style:{type:[String,Object],default:null}},setup(e){return(a,d)=>{const t=l;return s(),i(t,{code:e.code,language:e.language,filename:e.filename,highlights:e.highlights,meta:e.meta},{default:o(()=>[r("pre",{class:g(a.$props.class),style:u(e.style)},[f(a.$slots,"default")],6)]),_:3},8,["code","language","filename","highlights","meta"])}}});export{h as default}; +import{_ as l}from"./WSSBFWCz.js";import{d as n,o as s,e as i,f as o,b as r,l as g,a9 as u,a8 as f}from"./K1dcBiIN.js";const h=n({__name:"ProsePre",props:{code:{type:String,default:""},language:{type:String,default:null},filename:{type:String,default:null},highlights:{type:Array,default:()=>[]},meta:{type:String,default:null},class:{type:String,default:null},style:{type:[String,Object],default:null}},setup(e){return(a,d)=>{const t=l;return s(),i(t,{code:e.code,language:e.language,filename:e.filename,highlights:e.highlights,meta:e.meta},{default:o(()=>[r("pre",{class:g(a.$props.class),style:u(e.style)},[f(a.$slots,"default")],6)]),_:3},8,["code","language","filename","highlights","meta"])}}});export{h as default}; diff --git a/_nuxt/Dnd51l0P.js b/_nuxt/Dnd51l0P.js deleted file mode 100644 index 64cd7557..00000000 --- a/_nuxt/Dnd51l0P.js +++ /dev/null @@ -1 +0,0 @@ -const y=["p","h1","h2","h3","h4","h5","h6","li"];function f(r,t){return r.type===t||typeof r.type=="object"&&r.type.tag===t||r.tag===t}function u(r){return f(r,"text")||f(r,Symbol.for("v-txt"))}function l(r){var t;return Array.isArray(r.children)||typeof r.children=="string"?r.children:typeof((t=r.children)==null?void 0:t.default)=="function"?r.children.default():[]}function n(r){if(!r)return"";if(Array.isArray(r))return r.map(n).join("");if(u(r))return r.children||r.value||"";const t=l(r);return Array.isArray(t)?t.map(n).filter(Boolean).join(""):""}function h(r,t=[]){if(Array.isArray(r))return r.flatMap(e=>h(e,t));let i=r;return t.some(e=>e==="*"||f(r,e))&&(i=l(r)||r,!Array.isArray(i)&&y.some(e=>f(r,e))&&(i=[i])),i}function p(r,t=[]){return r=Array.isArray(r)?r:[r],t.length?r.flatMap(i=>p(h(i,[t[0]]),t.slice(1))).filter(i=>!(u(i)&&n(i).trim()==="")):r}function a(r,t=[]){return typeof t=="string"&&(t=t.split(",").map(i=>i.trim()).filter(Boolean)),t.length?p(r,t).reduce((i,e)=>(u(e)?typeof i[i.length-1]=="string"?i[i.length-1]+=e.children:i.push(e.children):i.push(e),i),[]):r}export{a as f}; diff --git a/_nuxt/DrUr0h-s.js b/_nuxt/DrUr0h-s.js deleted file mode 100644 index f29f9b14..00000000 --- a/_nuxt/DrUr0h-s.js +++ /dev/null @@ -1 +0,0 @@ -import{m as w,o as c,c as f,p as y,j as n,q as v,a as s,l as p,i as u,h as x,b as t,t as i,F as _}from"./CZZfhpmp.js";const V={},k={version:"1.1",id:"Layer_1",xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",x:"0px",y:"0px",viewBox:"0 0 1160 1160","enable-background":"new 0 0 1160 1160","xml:space":"preserve"};function H(o,e){return c(),f("svg",k,e[0]||(e[0]=[y('',2)]))}const M=w(V,[["render",H]]),S=window.setInterval,C={class:"bg-slate-800"},P={class:"flex h-screen items-center justify-center"},z={class:"mb-4 space-y-2 text-sm"},B={class:"flex items-center"},j={class:"flex-none pl-2"},F={class:"flex items-center"},N={class:"flex-none pl-2"},W="TL;DR",$={__name:"card",setup(o){const e=n(!1),l=n(0),a=n(0),h=(g,r)=>g[r%g.length];v(()=>{S(function(){l.value>a.value?a.value+=1:l.value+=1},1500)});const m=["Skydiving","Bungee jumping","Rock climbing","White water rafting","Paragliding","Scuba diving","Base jumping","Mountain biking","Surfing","Snowboarding","Wakeboarding","Motorsports","Parkour","Zip-lining","Off-roading","Cave diving","Kiteboarding","Hang gliding","Free solo climbing","Bull riding","Ice climbing","Wing suit flying","Extreme skiing","Cliff jumping","Cave exploring"],d=["Astronaut","Archaeologist","Professional athlete","Chef","Fashion designer","Film director","Investigative journalist","Marine biologist","Musician","Photographer","Pilot","Professional gamer","Professor","Sculptor","Spy","Stand-up comedian","Surfing instructor","Travel writer","Wildlife photographer","Wine connoisseur","Yacht captain","Yoga instructor","Zookeeper","Adventure tour guide","Art curator"];return(g,r)=>{const b=M;return c(),f(_,null,[s(e)?(c(),f("div",{key:0,class:p(["absolute bottom-2 right-2 h-24 w-24",g.dynamic_bg])},[u(b)],2)):x("",!0),t("main",C,[t("div",P,[t("div",{id:"_card",onClick:r[0]||(r[0]=A=>e.value=!s(e)),class:"md:w-512px w-[350px] border border-white bg-black p-4 font-mono uppercase text-white shadow-xl shadow-yellow-950 transition-all hover:scale-102 hover:cursor-pointer"},[t("div",{class:"mb-2 font-extrabold tracking-wide"},i(W)),t("div",z,[r[5]||(r[5]=t("div",{class:"flex items-center"},[t("div",{class:"flex-none pr-2"},"Name"),t("div",{class:"flex-grow border-b border-dotted"}),t("div",{class:"flex-none pl-2"},"Colton")],-1)),t("div",B,[r[1]||(r[1]=t("div",{class:"flex-none pr-2"},"Profession",-1)),r[2]||(r[2]=t("div",{class:"flex-grow border-b border-dotted"},null,-1)),t("div",j,i(h(d,s(l))),1)]),t("div",F,[r[3]||(r[3]=t("div",{class:"flex-none pr-2"},"Hobby",-1)),r[4]||(r[4]=t("div",{class:"flex-grow border-b border-dotted"},null,-1)),t("div",N,i(h(m,s(a))),1)])])])])])],64)}}};export{$ as default}; diff --git a/_nuxt/DsILVI33.js b/_nuxt/DsILVI33.js new file mode 100644 index 00000000..e9ccc30e --- /dev/null +++ b/_nuxt/DsILVI33.js @@ -0,0 +1 @@ +import{m as s,c as n,b as t,a8 as a,i as l,f as c,_ as r,o as i}from"./K1dcBiIN.js";const d={},_={class:"container mx-auto my-12 h-screen bg-background font-display lg:my-16"},h={class:"flex flex-col border-2 bg-white"},u={class:"absolute left-2 top-2"},f=t("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor",class:"mr-2 h-6 w-6"},[t("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15M12 9l-3 3m0 0l3 3m-3-3h12.75"})],-1),m=t("span",null,"Back",-1);function p(e,x){const o=r;return i(),n("main",null,[t("div",_,[t("div",h,[a(e.$slots,"default")])]),t("div",u,[l(o,{as:"button",to:"/playground",class:"inline-flex items-center rounded px-4 py-2 font-bold text-white hover:text-cyan"},{default:c(()=>[f,m]),_:1})])])}const g=s(d,[["render",p]]);export{g as default}; diff --git a/_nuxt/DSVbkqRh.js b/_nuxt/DsRHAFuR.js similarity index 92% rename from _nuxt/DSVbkqRh.js rename to _nuxt/DsRHAFuR.js index d53f08d1..18914996 100644 --- a/_nuxt/DSVbkqRh.js +++ b/_nuxt/DsRHAFuR.js @@ -1 +1 @@ -import{u as g}from"./BT7WDeVb.js";import{q as m}from"./CmpoAw97.js";import{d as C,P as S,k as b,I as k,v as _,J as A,L as N}from"./CZZfhpmp.js";import{h as O}from"./DvDH6DOc.js";import"./B2jTtLqC.js";const Q=C({name:"ContentQuery",props:{path:{type:String,required:!1,default:void 0},only:{type:Array,required:!1,default:void 0},without:{type:Array,required:!1,default:void 0},where:{type:Object,required:!1,default:void 0},sort:{type:Object,required:!1,default:void 0},limit:{type:Number,required:!1,default:void 0},skip:{type:Number,required:!1,default:void 0},locale:{type:String,required:!1,default:void 0},find:{type:String,required:!1,default:void 0}},async setup(u){const{path:t,only:r,without:o,where:a,sort:f,limit:l,skip:d,locale:s,find:p}=S(u),y=b(()=>{var e;return(e=t.value)==null?void 0:e.includes("/_")}),h=!k().public.content.experimental.advanceQuery;_(()=>u,()=>n(),{deep:!0});const i=e=>h?e!=null&&e.surround?e.surround:e!=null&&e._id||Array.isArray(e)?e:e==null?void 0:e.result:e.result,{data:v,refresh:n}=await g(`content-query-${O(u)}`,()=>{let e;return t.value?e=m(t.value):e=m(),r.value&&(e=e.only(r.value)),o.value&&(e=e.without(o.value)),a.value&&(e=e.where(a.value)),f.value&&(e=e.sort(f.value)),l.value&&(e=e.limit(l.value)),d.value&&(e=e.skip(d.value)),s.value&&(e=e.where({_locale:s.value})),p.value==="one"?e.findOne().then(i):p.value==="surround"?t.value?h?e.findSurround(t.value):e.withSurround(t.value).findOne().then(i):(console.warn("[Content] Surround queries requires `path` prop to be set."),console.warn("[Content] Query without `path` will return regular `find()` results."),e.find().then(i)):e.find().then(i)});return{isPartial:y,data:v,refresh:n}},render(u){var c;const t=A(),{data:r,refresh:o,isPartial:a,path:f,only:l,without:d,where:s,sort:p,limit:y,skip:h,locale:i,find:v}=u,n={path:f,only:l,without:d,where:s,sort:p,limit:y,skip:h,locale:i,find:v};if(n.find==="one"){if(!r&&(t!=null&&t["not-found"]))return t["not-found"]({props:n,...this.$attrs});if(t!=null&&t.empty&&(r==null?void 0:r._type)==="markdown"&&!((c=r==null?void 0:r.body)!=null&&c.children.length))return t.empty({props:n,...this.$attrs})}else if((!r||!r.length)&&t!=null&&t["not-found"])return t["not-found"]({props:n,...this.$attrs});return t!=null&&t.default?t.default({data:r,refresh:o,isPartial:a,props:n,...this.$attrs}):((w,q)=>N("pre",null,JSON.stringify({message:"You should use slots with !",slot:w,data:q},null,2)))("default",{data:r,props:n,isPartial:a})}}),J=Q;export{J as default}; +import{u as g}from"./C6WZwVE2.js";import{q as m}from"./Ce34VGij.js";import{d as C,P as S,k as b,I as k,v as _,J as A,L as N}from"./K1dcBiIN.js";import{h as O}from"./DvDH6DOc.js";import"./NnUIAPGH.js";const Q=C({name:"ContentQuery",props:{path:{type:String,required:!1,default:void 0},only:{type:Array,required:!1,default:void 0},without:{type:Array,required:!1,default:void 0},where:{type:Object,required:!1,default:void 0},sort:{type:Object,required:!1,default:void 0},limit:{type:Number,required:!1,default:void 0},skip:{type:Number,required:!1,default:void 0},locale:{type:String,required:!1,default:void 0},find:{type:String,required:!1,default:void 0}},async setup(u){const{path:t,only:r,without:o,where:a,sort:f,limit:l,skip:d,locale:s,find:p}=S(u),y=b(()=>{var e;return(e=t.value)==null?void 0:e.includes("/_")}),h=!k().public.content.experimental.advanceQuery;_(()=>u,()=>n(),{deep:!0});const i=e=>h?e!=null&&e.surround?e.surround:e!=null&&e._id||Array.isArray(e)?e:e==null?void 0:e.result:e.result,{data:v,refresh:n}=await g(`content-query-${O(u)}`,()=>{let e;return t.value?e=m(t.value):e=m(),r.value&&(e=e.only(r.value)),o.value&&(e=e.without(o.value)),a.value&&(e=e.where(a.value)),f.value&&(e=e.sort(f.value)),l.value&&(e=e.limit(l.value)),d.value&&(e=e.skip(d.value)),s.value&&(e=e.where({_locale:s.value})),p.value==="one"?e.findOne().then(i):p.value==="surround"?t.value?h?e.findSurround(t.value):e.withSurround(t.value).findOne().then(i):(console.warn("[Content] Surround queries requires `path` prop to be set."),console.warn("[Content] Query without `path` will return regular `find()` results."),e.find().then(i)):e.find().then(i)});return{isPartial:y,data:v,refresh:n}},render(u){var c;const t=A(),{data:r,refresh:o,isPartial:a,path:f,only:l,without:d,where:s,sort:p,limit:y,skip:h,locale:i,find:v}=u,n={path:f,only:l,without:d,where:s,sort:p,limit:y,skip:h,locale:i,find:v};if(n.find==="one"){if(!r&&(t!=null&&t["not-found"]))return t["not-found"]({props:n,...this.$attrs});if(t!=null&&t.empty&&(r==null?void 0:r._type)==="markdown"&&!((c=r==null?void 0:r.body)!=null&&c.children.length))return t.empty({props:n,...this.$attrs})}else if((!r||!r.length)&&t!=null&&t["not-found"])return t["not-found"]({props:n,...this.$attrs});return t!=null&&t.default?t.default({data:r,refresh:o,isPartial:a,props:n,...this.$attrs}):((w,q)=>N("pre",null,JSON.stringify({message:"You should use slots with !",slot:w,data:q},null,2)))("default",{data:r,props:n,isPartial:a})}}),J=Q;export{J as default}; diff --git a/_nuxt/BExJZFgy.js b/_nuxt/Dw08bDjX.js similarity index 75% rename from _nuxt/BExJZFgy.js rename to _nuxt/Dw08bDjX.js index 842cf781..ace88481 100644 --- a/_nuxt/BExJZFgy.js +++ b/_nuxt/Dw08bDjX.js @@ -1 +1 @@ -import{m as g,c as u,b as n,C as d,D as a,t as c,o as h}from"./CZZfhpmp.js";const p={data(){return{height:0,width:0,distance:3,strokeWidth:1,startingX:125,startingY:150,startingAngle:0,sequence:"3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275900994657640789512694683983525957098258226205224894077267194782684826014769909026401363944374553050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382686838689427741559918559252459539594310499725246808459872736446958486538367362226260991246080512438843904512441365497627807977156914359977001296160894416948685558484063534220722258284886481584560285060168427394522674676788952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288797108931456691368672287489405601015033086179286809208747609178249385890097149096759852613655497818931297848216829989487226588048575640142704775551323796414515237462343645428584447952658678210511413547357395231134271661021359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435064302184531910484810053706146806749192781911979399520614196634287544406437451237181921799983910159195618146751426912397489409071864942319615679452080951465502252316038819301420937621378559566389377870830390697920773467221825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539057962685610055081066587969981635747363840525714591028970641401109712062804390397595156771577004203378699360072305587631763594218731251471205329281918261861258673215791984148488291644706095752706957220917567116722910981690915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398315019701651511685171437657618351556508849099898599823873455283316355076479185358932261854896321329330898570642046752590709154814165498594616371802709819943099244889575712828905923233260972997120844335732654893823911932597463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100449293215160842444859637669838952286847831235526582131449576857262433441893039686426243410773226978028073189154411010446823252716201052652272111660396665573092547110557853763466820653109896526918620564769312570586356620185581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318586769751456614068007002378776591344017127494704205622305389945613140711270004078547332699390814546646458807972708266830634328587856983052358089330657574067954571637752542021149557615814002501262285941302164715509792592309907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111790429782856475032031986915140287080859904801094121472213179476477726224142548545403321571853061422881375850430633217518297986622371721591607716692547487389866549494501146540628433663937900397692656721463853067360965712091807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862947265473642523081770367515906735023507283540567040386743513622224771589150495309844489333096340878076932599397805419341447377441842631298608099888687413260472156951623965864573021631598193195167353812974167729478672422924654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001593776471651228935786015881617557829735233446042815126272037343146531977774160319906655418763979293344195215413418994854447345673831624993419131814809277771038638773431772075456545322077709212019051660962804909263601975988281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267945612753181340783303362542327839449753824372058353114771199260638133467768796959703098339130771098704085913374641442822772634659470474587847787201927715280731767907707157213444730605700733492436931138350493163128404251219256517980694113528013147013047816437885185290928545201165839341965621349143415956258658655705526904965209858033850722426482939728584783163057777560688876446248246857926039535277348030480290058760758251047470916439613626760449256274204208320856611906254543372131535958450687724602901618766795240616342522577195429162991930645537799140373404328752628889639958794757291746426357455254079091451357111369410911939325191076020825202618798531887705842972591677813149699009019211697173727847684726860849003377024242916513005005168323364350389517029893922334517220138128069650117844087451960121228599371623130171144484640903890644954440061986907548516026327505298349187407866808818338510228334508504860825039302133219715518430635455007668282949304137765527939751754613953984683393638304746119966538581538420568533862186725233402830871123282789212507712629463229563989898935821167456270102183564622013496715188190973038119800497340723961036854066431939509790190699639552453005450580685501956730229219139339185680344903982059551002263535361920419947455385938102343955449597783779023742161727111723643435439478221818528624085140066604433258885698670543154706965747458550332323342107301545940516553790686627333799585115625784322988273723198987571415957811196358330059408730681216028764962867446047746491599505497374256269010490377819868359381465741268049256487985561453723478673303904688383436346553794986419270563872931748723320837601123029911367938627089438799362016295154133714248928307220126901475466847653576164773794675200490757155527819653621323926406160136358155907422020203187277605277219005561484255518792530343513984425322341576233610642506390497500865627109535919465897514131034822769306247435363256916078154781811528436679570611086153315044521274739245449454236828860613408414863776700961207151249140430272538607648236341433462351897576645216413767969031495019108575984423919862916421939949072362346468441173940326591840443780513338945257423995082965912285085558215725031071257012668302402929525220118726767562204154205161841634847565169998116141010029960783869092916030288400269104140792886215078424516709087000699282120660418371806535567252532567532861291042487761825829765157959847035622262934860034158722980534989650226291748788202734209222245339856264766914905562842503912757710284027998066365825488926488025456610172967026640765590429099456815065265305371829412703369313785178609040708667114965583434347693385781711386455873678123014587687126603489139095620099393610310291616152881384379099042317473363948045759314931405297634757481193567091101377517210080315590248530906692037671922033229094334676851422144773793937517034436619910403375111735471918550464490263655128162288244625759163330391072253837421821408835086573917715096828874782656995995744906617583441375223970968340800535598491754173818839994469748676265516582765848358845314277568790029095170283529716344562129640435231176006651012412006597558512761785838292041974844236080071930457618932349229279650198751872127267507981255470958904556357921221033346697499235630254947802490114195212382815309114079073860251522742995818072471625916685451333123948049470791191532673430282441860414263639548000448002670496248201792896476697583183271314251702969234889627668440323260927524960357996469256504936818360900323809293459588970695365349406034021665443755890045632882250545255640564482465151875471196218443965825337543885690941130315095261793780029741207665147939425902989695946995565761218656196733786236256125216320862869222103274889218654364802296780705765615144632046927906821207388377814233562823608963208068222468012248261177185896381409183903673672220888321513755600372798394004152970028783076670944474560134556417254370906979396122571429894671543578468788614445812314593571984922528471605049221242470141214780573455105008019086996033027634787081081754501193071412233908663938339529425786905076431006383519834389341596131854347546495569781038293097164651438407007073604112373599843452251610507027056235266012764848308407611830130527932054274628654036036745328651057065874882256981579367897669742205750596834408697350201410206723585020072452256326513410559240190274216248439140359989535394590944070469120914093870012645600162374288021092764579310657922955249887275846101264836999892256959688159205600101655256375678",sketch:void 0}},methods:{render(i){const e="0123456789",o=["#FFBA08","#FAA307","#F48C06","#E85D04","#DC2F02","#D00000","#9D0208","#6A040F","#370617","#03071E"],r={x:this.startingX,y:this.startingY,a:this.startingAngle};i.strokeWeight(this.strokeWidth),i.clear(),i.background(o[9]),i.beginShape(),i.vertex(r.x,r.y);for(let t=0;t{o.setup=()=>{o.createCanvas(this.width,this.height),o.noLoop(),o.noFill(),o.stroke(255),this.sketch=o,this.render(this.sketch)}};new this.$p5(e,"canvas")}},m={class:"select-none bg-gradient-to-b from-green-800 to-gray-800"},x={class:"m-8 grid place-items-center"},b={class:"font-mono text-white"},f={class:"my-2 md:w-full"},v={class:"grid-rows-auto my-2 grid grid-cols-2 gap-4 border-2 border-white p-2 md:grid-rows-1"},k={class:"flex flex-col"},y={for:"distanceInput",class:"text-right"},w={class:"flex flex-col"},A={for:"strokeInput",class:"text-right"},_={class:"flex flex-col"},I={for:"startingXInput",class:"text-right"},C={class:"flex flex-col"},D={for:"startingYInput",class:"text-right"},V={class:"flex flex-col"},W={for:"startingAngleInput",class:"text-right"};function X(i,e,o,r,t,l){return h(),u("div",m,[n("div",x,[n("div",b,[e[11]||(e[11]=n("div",{id:"canvas-container",class:"mb-2 h-96 border-2 border-white"},[n("div",{id:"canvas"})],-1)),n("div",f,[d(n("textarea",{readonly:"","onUpdate:modelValue":e[0]||(e[0]=s=>t.sequence=s),class:"block h-24 w-full border-2 border-white bg-black p-2 text-white placeholder:italic placeholder:text-slate-400 focus:border-2 focus:border-yellow-500 focus:outline-none sm:text-sm",placeholder:"Enter a sequence of numbers...",type:"text"},null,512),[[a,t.sequence]])]),n("div",v,[n("div",k,[n("label",y,"Segment Length ["+c(t.distance)+"]",1),d(n("input",{id:"distanceInput","onUpdate:modelValue":e[1]||(e[1]=s=>t.distance=s),onChange:e[2]||(e[2]=s=>l.render(t.sketch)),type:"range",min:"1",max:"25",class:"accent-black"},null,544),[[a,t.distance,void 0,{number:!0}]])]),n("div",w,[n("label",A,"Stroke Width ["+c(t.strokeWidth)+"]",1),d(n("input",{id:"strokeInput","onUpdate:modelValue":e[3]||(e[3]=s=>t.strokeWidth=s),onChange:e[4]||(e[4]=s=>l.render(t.sketch)),type:"range",min:"1",max:"10",class:"accent-black"},null,544),[[a,t.strokeWidth,void 0,{number:!0}]])]),n("div",_,[n("label",I,"X Position ["+c(t.startingX)+"]",1),d(n("input",{id:"startingXInput","onUpdate:modelValue":e[5]||(e[5]=s=>t.startingX=s),onChange:e[6]||(e[6]=s=>l.render(t.sketch)),type:"range",min:"0",max:"500",class:"accent-black"},null,544),[[a,t.startingX,void 0,{number:!0}]])]),n("div",C,[n("label",D,"Y Position ["+c(t.startingY)+"]",1),d(n("input",{id:"startingYInput","onUpdate:modelValue":e[7]||(e[7]=s=>t.startingY=s),onChange:e[8]||(e[8]=s=>l.render(t.sketch)),type:"range",min:"0",max:"500",class:"accent-black"},null,544),[[a,t.startingY,void 0,{number:!0}]])]),n("div",V,[n("label",W,"Angle ["+c(t.startingAngle)+"]",1),d(n("input",{id:"startingAngleInput","onUpdate:modelValue":e[9]||(e[9]=s=>t.startingAngle=s),onChange:e[10]||(e[10]=s=>l.render(t.sketch)),type:"range",min:"-180",max:"180",class:"accent-black"},null,544),[[a,t.startingAngle,void 0,{number:!0}]])])])])])])}const E=g(p,[["render",X]]);export{E as default}; +import{m as g,c as h,b as n,C as d,D as c,t as a,o as u}from"./K1dcBiIN.js";const p={data(){return{height:0,width:0,distance:3,strokeWidth:1,startingX:125,startingY:150,startingAngle:0,sequence:"3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275900994657640789512694683983525957098258226205224894077267194782684826014769909026401363944374553050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382686838689427741559918559252459539594310499725246808459872736446958486538367362226260991246080512438843904512441365497627807977156914359977001296160894416948685558484063534220722258284886481584560285060168427394522674676788952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288797108931456691368672287489405601015033086179286809208747609178249385890097149096759852613655497818931297848216829989487226588048575640142704775551323796414515237462343645428584447952658678210511413547357395231134271661021359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435064302184531910484810053706146806749192781911979399520614196634287544406437451237181921799983910159195618146751426912397489409071864942319615679452080951465502252316038819301420937621378559566389377870830390697920773467221825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539057962685610055081066587969981635747363840525714591028970641401109712062804390397595156771577004203378699360072305587631763594218731251471205329281918261861258673215791984148488291644706095752706957220917567116722910981690915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398315019701651511685171437657618351556508849099898599823873455283316355076479185358932261854896321329330898570642046752590709154814165498594616371802709819943099244889575712828905923233260972997120844335732654893823911932597463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100449293215160842444859637669838952286847831235526582131449576857262433441893039686426243410773226978028073189154411010446823252716201052652272111660396665573092547110557853763466820653109896526918620564769312570586356620185581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318586769751456614068007002378776591344017127494704205622305389945613140711270004078547332699390814546646458807972708266830634328587856983052358089330657574067954571637752542021149557615814002501262285941302164715509792592309907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111790429782856475032031986915140287080859904801094121472213179476477726224142548545403321571853061422881375850430633217518297986622371721591607716692547487389866549494501146540628433663937900397692656721463853067360965712091807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862947265473642523081770367515906735023507283540567040386743513622224771589150495309844489333096340878076932599397805419341447377441842631298608099888687413260472156951623965864573021631598193195167353812974167729478672422924654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001593776471651228935786015881617557829735233446042815126272037343146531977774160319906655418763979293344195215413418994854447345673831624993419131814809277771038638773431772075456545322077709212019051660962804909263601975988281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267945612753181340783303362542327839449753824372058353114771199260638133467768796959703098339130771098704085913374641442822772634659470474587847787201927715280731767907707157213444730605700733492436931138350493163128404251219256517980694113528013147013047816437885185290928545201165839341965621349143415956258658655705526904965209858033850722426482939728584783163057777560688876446248246857926039535277348030480290058760758251047470916439613626760449256274204208320856611906254543372131535958450687724602901618766795240616342522577195429162991930645537799140373404328752628889639958794757291746426357455254079091451357111369410911939325191076020825202618798531887705842972591677813149699009019211697173727847684726860849003377024242916513005005168323364350389517029893922334517220138128069650117844087451960121228599371623130171144484640903890644954440061986907548516026327505298349187407866808818338510228334508504860825039302133219715518430635455007668282949304137765527939751754613953984683393638304746119966538581538420568533862186725233402830871123282789212507712629463229563989898935821167456270102183564622013496715188190973038119800497340723961036854066431939509790190699639552453005450580685501956730229219139339185680344903982059551002263535361920419947455385938102343955449597783779023742161727111723643435439478221818528624085140066604433258885698670543154706965747458550332323342107301545940516553790686627333799585115625784322988273723198987571415957811196358330059408730681216028764962867446047746491599505497374256269010490377819868359381465741268049256487985561453723478673303904688383436346553794986419270563872931748723320837601123029911367938627089438799362016295154133714248928307220126901475466847653576164773794675200490757155527819653621323926406160136358155907422020203187277605277219005561484255518792530343513984425322341576233610642506390497500865627109535919465897514131034822769306247435363256916078154781811528436679570611086153315044521274739245449454236828860613408414863776700961207151249140430272538607648236341433462351897576645216413767969031495019108575984423919862916421939949072362346468441173940326591840443780513338945257423995082965912285085558215725031071257012668302402929525220118726767562204154205161841634847565169998116141010029960783869092916030288400269104140792886215078424516709087000699282120660418371806535567252532567532861291042487761825829765157959847035622262934860034158722980534989650226291748788202734209222245339856264766914905562842503912757710284027998066365825488926488025456610172967026640765590429099456815065265305371829412703369313785178609040708667114965583434347693385781711386455873678123014587687126603489139095620099393610310291616152881384379099042317473363948045759314931405297634757481193567091101377517210080315590248530906692037671922033229094334676851422144773793937517034436619910403375111735471918550464490263655128162288244625759163330391072253837421821408835086573917715096828874782656995995744906617583441375223970968340800535598491754173818839994469748676265516582765848358845314277568790029095170283529716344562129640435231176006651012412006597558512761785838292041974844236080071930457618932349229279650198751872127267507981255470958904556357921221033346697499235630254947802490114195212382815309114079073860251522742995818072471625916685451333123948049470791191532673430282441860414263639548000448002670496248201792896476697583183271314251702969234889627668440323260927524960357996469256504936818360900323809293459588970695365349406034021665443755890045632882250545255640564482465151875471196218443965825337543885690941130315095261793780029741207665147939425902989695946995565761218656196733786236256125216320862869222103274889218654364802296780705765615144632046927906821207388377814233562823608963208068222468012248261177185896381409183903673672220888321513755600372798394004152970028783076670944474560134556417254370906979396122571429894671543578468788614445812314593571984922528471605049221242470141214780573455105008019086996033027634787081081754501193071412233908663938339529425786905076431006383519834389341596131854347546495569781038293097164651438407007073604112373599843452251610507027056235266012764848308407611830130527932054274628654036036745328651057065874882256981579367897669742205750596834408697350201410206723585020072452256326513410559240190274216248439140359989535394590944070469120914093870012645600162374288021092764579310657922955249887275846101264836999892256959688159205600101655256375678",sketch:void 0}},methods:{render(i){const e="0123456789",r=["#FFBA08","#FAA307","#F48C06","#E85D04","#DC2F02","#D00000","#9D0208","#6A040F","#370617","#03071E"],o={x:this.startingX,y:this.startingY,a:this.startingAngle};i.strokeWeight(this.strokeWidth),i.clear(),i.background(r[9]),i.beginShape(),i.vertex(o.x,o.y);for(let t=0;t{r.setup=()=>{r.createCanvas(this.width,this.height),r.noLoop(),r.noFill(),r.stroke(255),this.sketch=r,this.render(this.sketch)}};new this.$p5(e,"canvas")}},m={class:"select-none bg-gradient-to-b from-green-800 to-gray-800"},x={class:"m-8 grid place-items-center"},b={class:"font-mono text-white"},f=n("div",{id:"canvas-container",class:"mb-2 h-96 border-2 border-white"},[n("div",{id:"canvas"})],-1),v={class:"my-2 md:w-full"},k={class:"grid-rows-auto my-2 grid grid-cols-2 gap-4 border-2 border-white p-2 md:grid-rows-1"},_={class:"flex flex-col"},y={for:"distanceInput",class:"text-right"},w={class:"flex flex-col"},A={for:"strokeInput",class:"text-right"},I={class:"flex flex-col"},C={for:"startingXInput",class:"text-right"},D={class:"flex flex-col"},V={for:"startingYInput",class:"text-right"},W={class:"flex flex-col"},X={for:"startingAngleInput",class:"text-right"};function Y(i,e,r,o,t,l){return u(),h("div",m,[n("div",x,[n("div",b,[f,n("div",v,[d(n("textarea",{readonly:"","onUpdate:modelValue":e[0]||(e[0]=s=>t.sequence=s),class:"block h-24 w-full border-2 border-white bg-black p-2 text-white placeholder:italic placeholder:text-slate-400 focus:border-2 focus:border-yellow-500 focus:outline-none sm:text-sm",placeholder:"Enter a sequence of numbers...",type:"text"},null,512),[[c,t.sequence]])]),n("div",k,[n("div",_,[n("label",y,"Segment Length ["+a(t.distance)+"]",1),d(n("input",{id:"distanceInput","onUpdate:modelValue":e[1]||(e[1]=s=>t.distance=s),onChange:e[2]||(e[2]=s=>l.render(t.sketch)),type:"range",min:"1",max:"25",class:"accent-black"},null,544),[[c,t.distance,void 0,{number:!0}]])]),n("div",w,[n("label",A,"Stroke Width ["+a(t.strokeWidth)+"]",1),d(n("input",{id:"strokeInput","onUpdate:modelValue":e[3]||(e[3]=s=>t.strokeWidth=s),onChange:e[4]||(e[4]=s=>l.render(t.sketch)),type:"range",min:"1",max:"10",class:"accent-black"},null,544),[[c,t.strokeWidth,void 0,{number:!0}]])]),n("div",I,[n("label",C,"X Position ["+a(t.startingX)+"]",1),d(n("input",{id:"startingXInput","onUpdate:modelValue":e[5]||(e[5]=s=>t.startingX=s),onChange:e[6]||(e[6]=s=>l.render(t.sketch)),type:"range",min:"0",max:"500",class:"accent-black"},null,544),[[c,t.startingX,void 0,{number:!0}]])]),n("div",D,[n("label",V,"Y Position ["+a(t.startingY)+"]",1),d(n("input",{id:"startingYInput","onUpdate:modelValue":e[7]||(e[7]=s=>t.startingY=s),onChange:e[8]||(e[8]=s=>l.render(t.sketch)),type:"range",min:"0",max:"500",class:"accent-black"},null,544),[[c,t.startingY,void 0,{number:!0}]])]),n("div",W,[n("label",X,"Angle ["+a(t.startingAngle)+"]",1),d(n("input",{id:"startingAngleInput","onUpdate:modelValue":e[9]||(e[9]=s=>t.startingAngle=s),onChange:e[10]||(e[10]=s=>l.render(t.sketch)),type:"range",min:"-180",max:"180",class:"accent-black"},null,544),[[c,t.startingAngle,void 0,{number:!0}]])])])])])])}const F=g(p,[["render",Y]]);export{F as default}; diff --git a/_nuxt/BsueCq5A.js b/_nuxt/Dyf09I7x.js similarity index 65% rename from _nuxt/BsueCq5A.js rename to _nuxt/Dyf09I7x.js index 03687513..68dc8061 100644 --- a/_nuxt/BsueCq5A.js +++ b/_nuxt/Dyf09I7x.js @@ -1 +1 @@ -import{m as o,o as t,c,a8 as r}from"./CZZfhpmp.js";const s={};function n(e,a){return t(),c("blockquote",null,[r(e.$slots,"default")])}const f=o(s,[["render",n]]);export{f as default}; +import{m as o,o as t,c,a8 as r}from"./K1dcBiIN.js";const s={};function n(e,a){return t(),c("blockquote",null,[r(e.$slots,"default")])}const f=o(s,[["render",n]]);export{f as default}; diff --git a/_nuxt/Ie0IFvhY.js b/_nuxt/Ie0IFvhY.js deleted file mode 100644 index d0c0de17..00000000 --- a/_nuxt/Ie0IFvhY.js +++ /dev/null @@ -1 +0,0 @@ -import{m as u,c as m,b as c,o as p}from"./CZZfhpmp.js";const v={data(){return{}},mounted(){const a=["#FFBA08","#FAA307","#F48C06","#E85D04","#DC2F02","#D00000","#9D0208","#6A040F","#370617","#03071E"],s=e=>{const i=t=>e.unhex([t.slice(1,3),t.slice(3,5),t.slice(5,7)]),d=(t,o)=>t.map(n=>{const r=e.floor(n+e.random(-o,o));return r<0?0:r>255?255:r});e.setup=()=>{e.createCanvas(400,400),e.frameRate(5)},e.draw=()=>{e.background(0,0,0),e.noStroke(),e.noFill();const t=9,o=400/t;for(let n=0;n<=t;n++)for(let r=0;r<=t;r++){const f=a[r%9];e.fill(d(i(f),15)),e.square(n*o,r*o,o)}}};new this.$p5(s,"canvas")}},I={class:"bg-gradient-to-b from-green-800 to-gray-800"};function b(a,s,e,i,d,l){return p(),m("div",I,s[0]||(s[0]=[c("div",{class:"grid h-screen place-items-center"},[c("div",{class:"font-mono text-white"},[c("div",{class:"mb-2 border-2 border-white"},[c("div",{id:"canvas"})])])],-1)]))}const _=u(v,[["render",b]]);export{_ as default}; diff --git a/_nuxt/Iio6RtF1.js b/_nuxt/Iio6RtF1.js new file mode 100644 index 00000000..e0e35cc9 --- /dev/null +++ b/_nuxt/Iio6RtF1.js @@ -0,0 +1 @@ +import{d as i,I as c,k as p,o as s,c as n,a as u,a8 as t}from"./K1dcBiIN.js";const f=["id"],l=["href"],k=i({__name:"ProseH6",props:{id:{}},setup(a){const r=a,{headings:o}=c().public.mdc,d=p(()=>{var e;return r.id&&((e=o==null?void 0:o.anchorLinks)==null?void 0:e.h6)});return(e,m)=>(s(),n("h6",{id:e.id},[e.id&&u(d)?(s(),n("a",{key:0,href:`#${e.id}`},[t(e.$slots,"default")],8,l)):t(e.$slots,"default",{key:1})],8,f))}});export{k as default}; diff --git a/_nuxt/IzO1sTXP.js b/_nuxt/IzO1sTXP.js new file mode 100644 index 00000000..3955b4a1 --- /dev/null +++ b/_nuxt/IzO1sTXP.js @@ -0,0 +1 @@ +import{u as A,j as g,w as R,k as m,c as r,b as s,F as d,r as v,a as c,h as S,o as l,t as _,i as f,f as y,g as D,l as C,_ as F}from"./K1dcBiIN.js";import{_ as L}from"./y2Up_N_N.js";import j from"./mDMTOJLw.js";import{u as z}from"./C6WZwVE2.js";import{q as E}from"./Ce34VGij.js";import"./C-v3KzvZ.js";import"./NnUIAPGH.js";import"./DvDH6DOc.js";const M={class:"container mx-auto font-mono text-white"},G=s("h1",{class:"my-6 text-2xl font-extrabold"},"Blog",-1),H={class:"grid grid-cols-4 gap-4"},I={class:"col-span-4 lg:col-span-3"},J={class:"grid grid-cols-10 gap-y-4 lg:gap-y-6"},K={class:"col-span-10 lg:col-span-2"},O={class:"col-span-10 lg:col-span-8"},P={class:"flex-col space-y-2"},Q={class:"col-span-4 border-l border-gray-700 pl-4 lg:col-span-1"},U={class:"my-2 space-y-2"},W=s("p",{class:"text-xl font-bold"},"Categories",-1),X=["onClick"],Y={key:0,class:"my-2 space-y-2"},Z=s("p",{class:"text-xl font-bold"},"Tags",-1),ee=["onClick"],de={__name:"index",async setup(te){let i,h;const u=A(),o=g([]);u.query.category&&(o.value=[u.query.category]);const a=g([]);u.query.tag&&(a.value=[u.query.tag]);const k=g(!0),{data:p}=([i,h]=R(()=>z("articles",()=>E().only(["_id","_path","title","description","date","img","author","tags","categories","img","excerpt","summary"]).sort({date:-1}).find())),i=await i,h(),i),w=m(()=>[...new Set(p.value.map(e=>e.categories).flat().sort())]),b=m(()=>[...new Set(p.value.map(e=>e.tags).flat().sort())]),q=m(()=>p.value.filter(e=>!(o.value.length>0&&!o.value.every(n=>e.categories.includes(n))||a.value.length>0&&!a.value.every(n=>e.tags.includes(n)))));function N(e){a.value.includes(e)?a.value=a.value.filter(n=>n!==e):a.value.push(e)}function T(e){o.value.includes(e)?o.value=o.value.filter(n=>n!==e):o.value.push(e)}return(e,n)=>{const B=F,V=L,$=j;return l(),r("section",M,[G,s("div",H,[s("div",I,[s("div",J,[(l(!0),r(d,null,v(c(q),t=>(l(),r(d,{key:t._id},[s("div",K,_(t.date),1),s("div",O,[s("div",P,[f(B,{class:"text-orange-500",to:t._path},{default:y(()=>[D(_(t.title),1)]),_:2},1032,["to"]),f($,{value:t},{default:y(()=>[f(V,{class:"line-clamp-5 text-xs text-gray-400",value:{body:t.excerpt}},null,8,["value"])]),_:2},1032,["value"])])])],64))),128))])]),s("div",Q,[s("div",U,[W,(l(!0),r(d,null,v(c(w),t=>(l(),r("div",{key:t,class:C([{"bg-orange-500rtext-white":c(o).includes(t)},"cursor-pointer p-1 text-sm text-gray-400 hover:bg-orange-500 hover:text-white"]),onClick:x=>T(t)},_(t),11,X))),128))]),c(k)?(l(),r("div",Y,[Z,(l(!0),r(d,null,v(c(b),(t,x)=>(l(),r("div",{key:x,class:C([{"bg-orange-500 text-white":c(a).includes(t)},"cursor-pointer select-none p-1 text-sm text-gray-400 hover:bg-orange-500 hover:text-white"]),onClick:se=>N(t)},_(t),11,ee))),128))])):S("",!0)])])])}}};export{de as default}; diff --git a/_nuxt/K1dcBiIN.js b/_nuxt/K1dcBiIN.js new file mode 100644 index 00000000..9af44b02 --- /dev/null +++ b/_nuxt/K1dcBiIN.js @@ -0,0 +1,1650 @@ +const __vite__fileDeps=["./g5yxyt4Q.js","./y2Up_N_N.js","./C-v3KzvZ.js","./NnUIAPGH.js","./DvDH6DOc.js","./mDMTOJLw.js","./C6WZwVE2.js","./Ce34VGij.js","./_...J8jiN4NX.css","./IzO1sTXP.js","./BPNqVqzl.js","./Bildd8lj.js","./OorYyVAq.js","./DOZLo8mA.js","./v3tOoUxe.js","./DsRHAFuR.js","./CS4CKjMH.js","./DjOkkdqj.js","./uYek0qF_.js","./pTPauEmS.js","./-GjkDpfn.js","./D-xzt0Hk.js","./WSSBFWCz.js","./ProseCode.CchFRBtv.css","./DltOabO9.js"],__vite__mapDeps=i=>i.map(i=>__vite__fileDeps[i]); +/** +* @vue/shared v3.4.25 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**//*! #__NO_SIDE_EFFECTS__ */function Ba(r,d){const w=new Set(r.split(","));return t=>w.has(t)}const Lt={},lo=[],Vr=()=>{},Rh=()=>!1,os=r=>r.charCodeAt(0)===111&&r.charCodeAt(1)===110&&(r.charCodeAt(2)>122||r.charCodeAt(2)<97),Ga=r=>r.startsWith("onUpdate:"),Yt=Object.assign,Va=(r,d)=>{const w=r.indexOf(d);w>-1&&r.splice(w,1)},Lh=Object.prototype.hasOwnProperty,vt=(r,d)=>Lh.call(r,d),st=Array.isArray,uo=r=>ss(r)==="[object Map]",Gc=r=>ss(r)==="[object Set]",Ih=r=>ss(r)==="[object RegExp]",at=r=>typeof r=="function",Gt=r=>typeof r=="string",eo=r=>typeof r=="symbol",Ot=r=>r!==null&&typeof r=="object",Ha=r=>(Ot(r)||at(r))&&at(r.then)&&at(r.catch),Vc=Object.prototype.toString,ss=r=>Vc.call(r),Dh=r=>ss(r).slice(8,-1),Hc=r=>ss(r)==="[object Object]",za=r=>Gt(r)&&r!=="NaN"&&r[0]!=="-"&&""+parseInt(r,10)===r,co=Ba(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),ni=r=>{const d=Object.create(null);return w=>d[w]||(d[w]=r(w))},Fh=/-(\w)/g,an=ni(r=>r.replace(Fh,(d,w)=>w?w.toUpperCase():"")),Nh=/\B([A-Z])/g,xo=ni(r=>r.replace(Nh,"-$1").toLowerCase()),oi=ni(r=>r.charAt(0).toUpperCase()+r.slice(1)),Ci=ni(r=>r?`on${oi(r)}`:""),Dn=(r,d)=>!Object.is(r,d),fo=(r,d)=>{for(let w=0;w{Object.defineProperty(r,d,{configurable:!0,enumerable:!1,value:w})},oa=r=>{const d=parseFloat(r);return isNaN(d)?r:d},Wc=r=>{const d=Gt(r)?Number(r):NaN;return isNaN(d)?r:d};let cu;const qc=()=>cu||(cu=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Wa(r){if(st(r)){const d={};for(let w=0;w{if(w){const t=w.split(Bh);t.length>1&&(d[t[0].trim()]=t[1].trim())}}),d}function Yn(r){let d="";if(Gt(r))d=r;else if(st(r))for(let w=0;wGt(r)?r:r==null?"":st(r)||Ot(r)&&(r.toString===Vc||!at(r.toString))?JSON.stringify(r,Yc,2):String(r),Yc=(r,d)=>d&&d.__v_isRef?Yc(r,d.value):uo(d)?{[`Map(${d.size})`]:[...d.entries()].reduce((w,[t,x],v)=>(w[Oi(t,v)+" =>"]=x,w),{})}:Gc(d)?{[`Set(${d.size})`]:[...d.values()].map(w=>Oi(w))}:eo(d)?Oi(d):Ot(d)&&!st(d)&&!Hc(d)?String(d):d,Oi=(r,d="")=>{var w;return eo(r)?`Symbol(${(w=r.description)!=null?w:d})`:r};/** +* @vue/reactivity v3.4.25 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let Lr;class $c{constructor(d=!1){this.detached=d,this._active=!0,this.effects=[],this.cleanups=[],this.parent=Lr,!d&&Lr&&(this.index=(Lr.scopes||(Lr.scopes=[])).push(this)-1)}get active(){return this._active}run(d){if(this._active){const w=Lr;try{return Lr=this,d()}finally{Lr=w}}}on(){Lr=this}off(){Lr=this.parent}stop(d){if(this._active){let w,t;for(w=0,t=this.effects.length;w=4))break}this._dirtyLevel===1&&(this._dirtyLevel=0),Nn()}return this._dirtyLevel>=4}set dirty(d){this._dirtyLevel=d?4:0}run(){if(this._dirtyLevel=0,!this.active)return this.fn();let d=Rn,w=$n;try{return Rn=!0,$n=this,this._runnings++,du(this),this.fn()}finally{fu(this),this._runnings--,$n=w,Rn=d}}stop(){var d;this.active&&(du(this),fu(this),(d=this.onStop)==null||d.call(this),this.active=!1)}}function Yh(r){return r.value}function du(r){r._trackId++,r._depsLength=0}function fu(r){if(r.deps.length>r._depsLength){for(let d=r._depsLength;d{const w=new Map;return w.cleanup=r,w.computed=d,w},Gs=new WeakMap,Zn=Symbol(""),aa=Symbol("");function br(r,d,w){if(Rn&&$n){let t=Gs.get(r);t||Gs.set(r,t=new Map);let x=t.get(w);x||t.set(w,x=ed(()=>t.delete(w))),Qc($n,x)}}function pn(r,d,w,t,x,v){const s=Gs.get(r);if(!s)return;let u=[];if(d==="clear")u=[...s.values()];else if(w==="length"&&st(r)){const o=Number(t);s.forEach((c,g)=>{(g==="length"||!eo(g)&&g>=o)&&u.push(c)})}else switch(w!==void 0&&u.push(s.get(w)),d){case"add":st(r)?za(w)&&u.push(s.get("length")):(u.push(s.get(Zn)),uo(r)&&u.push(s.get(aa)));break;case"delete":st(r)||(u.push(s.get(Zn)),uo(r)&&u.push(s.get(aa)));break;case"set":uo(r)&&u.push(s.get(Zn));break}Xa();for(const o of u)o&&Jc(o,4);Ya()}function $h(r,d){var w;return(w=Gs.get(r))==null?void 0:w.get(d)}const Zh=Ba("__proto__,__v_isRef,__isVue"),td=new Set(Object.getOwnPropertyNames(Symbol).filter(r=>r!=="arguments"&&r!=="caller").map(r=>Symbol[r]).filter(eo)),hu=Kh();function Kh(){const r={};return["includes","indexOf","lastIndexOf"].forEach(d=>{r[d]=function(...w){const t=bt(this);for(let v=0,s=this.length;v{r[d]=function(...w){Fn(),Xa();const t=bt(this)[d].apply(this,w);return Ya(),Nn(),t}}),r}function Qh(r){eo(r)||(r=String(r));const d=bt(this);return br(d,"has",r),d.hasOwnProperty(r)}class rd{constructor(d=!1,w=!1){this._isReadonly=d,this._isShallow=w}get(d,w,t){const x=this._isReadonly,v=this._isShallow;if(w==="__v_isReactive")return!x;if(w==="__v_isReadonly")return x;if(w==="__v_isShallow")return v;if(w==="__v_raw")return t===(x?v?dp:id:v?sd:od).get(d)||Object.getPrototypeOf(d)===Object.getPrototypeOf(t)?d:void 0;const s=st(d);if(!x){if(s&&vt(hu,w))return Reflect.get(hu,w,t);if(w==="hasOwnProperty")return Qh}const u=Reflect.get(d,w,t);return(eo(w)?td.has(w):Zh(w))||(x||br(d,"get",w),v)?u:fr(u)?s&&za(w)?u:u.value:Ot(u)?x?ad(u):Un(u):u}}class nd extends rd{constructor(d=!1){super(!1,d)}set(d,w,t,x){let v=d[w];if(!this._isShallow){const o=yo(v);if(!Vs(t)&&!yo(t)&&(v=bt(v),t=bt(t)),!st(d)&&fr(v)&&!fr(t))return o?!1:(v.value=t,!0)}const s=st(d)&&za(w)?Number(w)r,si=r=>Reflect.getPrototypeOf(r);function ws(r,d,w=!1,t=!1){r=r.__v_raw;const x=bt(r),v=bt(d);w||(Dn(d,v)&&br(x,"get",d),br(x,"get",v));const{has:s}=si(x),u=t?$a:w?Qa:$o;if(s.call(x,d))return u(r.get(d));if(s.call(x,v))return u(r.get(v));r!==x&&r.get(d)}function xs(r,d=!1){const w=this.__v_raw,t=bt(w),x=bt(r);return d||(Dn(r,x)&&br(t,"has",r),br(t,"has",x)),r===x?w.has(r):w.has(r)||w.has(x)}function js(r,d=!1){return r=r.__v_raw,!d&&br(bt(r),"iterate",Zn),Reflect.get(r,"size",r)}function pu(r){r=bt(r);const d=bt(this);return si(d).has.call(d,r)||(d.add(r),pn(d,"add",r,r)),this}function mu(r,d){d=bt(d);const w=bt(this),{has:t,get:x}=si(w);let v=t.call(w,r);v||(r=bt(r),v=t.call(w,r));const s=x.call(w,r);return w.set(r,d),v?Dn(d,s)&&pn(w,"set",r,d):pn(w,"add",r,d),this}function yu(r){const d=bt(this),{has:w,get:t}=si(d);let x=w.call(d,r);x||(r=bt(r),x=w.call(d,r)),t&&t.call(d,r);const v=d.delete(r);return x&&pn(d,"delete",r,void 0),v}function gu(){const r=bt(this),d=r.size!==0,w=r.clear();return d&&pn(r,"clear",void 0,void 0),w}function Ss(r,d){return function(t,x){const v=this,s=v.__v_raw,u=bt(s),o=d?$a:r?Qa:$o;return!r&&br(u,"iterate",Zn),s.forEach((c,g)=>t.call(x,o(c),o(g),v))}}function Es(r,d,w){return function(...t){const x=this.__v_raw,v=bt(x),s=uo(v),u=r==="entries"||r===Symbol.iterator&&s,o=r==="keys"&&s,c=x[r](...t),g=w?$a:d?Qa:$o;return!d&&br(v,"iterate",o?aa:Zn),{next(){const{value:p,done:n}=c.next();return n?{value:p,done:n}:{value:u?[g(p[0]),g(p[1])]:g(p),done:n}},[Symbol.iterator](){return this}}}}function wn(r){return function(...d){return r==="delete"?!1:r==="clear"?void 0:this}}function np(){const r={get(v){return ws(this,v)},get size(){return js(this)},has:xs,add:pu,set:mu,delete:yu,clear:gu,forEach:Ss(!1,!1)},d={get(v){return ws(this,v,!1,!0)},get size(){return js(this)},has:xs,add:pu,set:mu,delete:yu,clear:gu,forEach:Ss(!1,!0)},w={get(v){return ws(this,v,!0)},get size(){return js(this,!0)},has(v){return xs.call(this,v,!0)},add:wn("add"),set:wn("set"),delete:wn("delete"),clear:wn("clear"),forEach:Ss(!0,!1)},t={get(v){return ws(this,v,!0,!0)},get size(){return js(this,!0)},has(v){return xs.call(this,v,!0)},add:wn("add"),set:wn("set"),delete:wn("delete"),clear:wn("clear"),forEach:Ss(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(v=>{r[v]=Es(v,!1,!1),w[v]=Es(v,!0,!1),d[v]=Es(v,!1,!0),t[v]=Es(v,!0,!0)}),[r,w,d,t]}const[op,sp,ip,ap]=np();function Za(r,d){const w=d?r?ap:ip:r?sp:op;return(t,x,v)=>x==="__v_isReactive"?!r:x==="__v_isReadonly"?r:x==="__v_raw"?t:Reflect.get(vt(w,x)&&x in t?w:t,x,v)}const lp={get:Za(!1,!1)},up={get:Za(!1,!0)},cp={get:Za(!0,!1)};const od=new WeakMap,sd=new WeakMap,id=new WeakMap,dp=new WeakMap;function fp(r){switch(r){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function hp(r){return r.__v_skip||!Object.isExtensible(r)?0:fp(Dh(r))}function Un(r){return yo(r)?r:Ka(r,!1,ep,lp,od)}function is(r){return Ka(r,!1,rp,up,sd)}function ad(r){return Ka(r,!0,tp,cp,id)}function Ka(r,d,w,t,x){if(!Ot(r)||r.__v_raw&&!(d&&r.__v_isReactive))return r;const v=x.get(r);if(v)return v;const s=hp(r);if(s===0)return r;const u=new Proxy(r,s===2?t:w);return x.set(r,u),u}function Uo(r){return yo(r)?Uo(r.__v_raw):!!(r&&r.__v_isReactive)}function yo(r){return!!(r&&r.__v_isReadonly)}function Vs(r){return!!(r&&r.__v_isShallow)}function ld(r){return r?!!r.__v_raw:!1}function bt(r){const d=r&&r.__v_raw;return d?bt(d):r}function pp(r){return Object.isExtensible(r)&&zc(r,"__v_skip",!0),r}const $o=r=>Ot(r)?Un(r):r,Qa=r=>Ot(r)?ad(r):r;class ud{constructor(d,w,t,x){this.getter=d,this._setter=w,this.dep=void 0,this.__v_isRef=!0,this.__v_isReadonly=!1,this.effect=new qa(()=>d(this._value),()=>Bo(this,this.effect._dirtyLevel===2?2:3)),this.effect.computed=this,this.effect.active=this._cacheable=!x,this.__v_isReadonly=t}get value(){const d=bt(this);return(!d._cacheable||d.effect.dirty)&&Dn(d._value,d._value=d.effect.run())&&Bo(d,4),Ja(d),d.effect._dirtyLevel>=2&&Bo(d,2),d._value}set value(d){this._setter(d)}get _dirty(){return this.effect.dirty}set _dirty(d){this.effect.dirty=d}}function mp(r,d,w=!1){let t,x;const v=at(r);return v?(t=r,x=Vr):(t=r.get,x=r.set),new ud(t,x,v||!x,w)}function Ja(r){var d;Rn&&$n&&(r=bt(r),Qc($n,(d=r.dep)!=null?d:r.dep=ed(()=>r.dep=void 0,r instanceof ud?r:void 0)))}function Bo(r,d=4,w){r=bt(r);const t=r.dep;t&&Jc(t,d)}function fr(r){return!!(r&&r.__v_isRef===!0)}function mt(r){return cd(r,!1)}function Zo(r){return cd(r,!0)}function cd(r,d){return fr(r)?r:new yp(r,d)}class yp{constructor(d,w){this.__v_isShallow=w,this.dep=void 0,this.__v_isRef=!0,this._rawValue=w?d:bt(d),this._value=w?d:$o(d)}get value(){return Ja(this),this._value}set value(d){const w=this.__v_isShallow||Vs(d)||yo(d);d=w?d:bt(d),Dn(d,this._rawValue)&&(this._rawValue=d,this._value=w?d:$o(d),Bo(this,4))}}function Bt(r){return fr(r)?r.value:r}function j_(r){return at(r)?r():Bt(r)}const gp={get:(r,d,w)=>Bt(Reflect.get(r,d,w)),set:(r,d,w,t)=>{const x=r[d];return fr(x)&&!fr(w)?(x.value=w,!0):Reflect.set(r,d,w,t)}};function dd(r){return Uo(r)?r:new Proxy(r,gp)}class vp{constructor(d){this.dep=void 0,this.__v_isRef=!0;const{get:w,set:t}=d(()=>Ja(this),()=>Bo(this));this._get=w,this._set=t}get value(){return this._get()}set value(d){this._set(d)}}function S_(r){return new vp(r)}function E_(r){const d=st(r)?new Array(r.length):{};for(const w in r)d[w]=fd(r,w);return d}class bp{constructor(d,w,t){this._object=d,this._key=w,this._defaultValue=t,this.__v_isRef=!0}get value(){const d=this._object[this._key];return d===void 0?this._defaultValue:d}set value(d){this._object[this._key]=d}get dep(){return $h(bt(this._object),this._key)}}class _p{constructor(d){this._getter=d,this.__v_isRef=!0,this.__v_isReadonly=!0}get value(){return this._getter()}}function wp(r,d,w){return fr(r)?r:at(r)?new _p(r):Ot(r)&&arguments.length>1?fd(r,d,w):mt(r)}function fd(r,d,w){const t=r[d];return fr(t)?t:new bp(r,d,w)}/** +* @vue/runtime-core v3.4.25 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function Ln(r,d,w,t){try{return t?r(...t):r()}catch(x){jo(x,d,w)}}function zr(r,d,w,t){if(at(r)){const x=Ln(r,d,w,t);return x&&Ha(x)&&x.catch(v=>{jo(v,d,w)}),x}if(st(r)){const x=[];for(let v=0;v>>1,x=dr[t],v=Qo(x);vsn&&dr.splice(d,1)}function ua(r){st(r)?ho.push(...r):(!Tn||!Tn.includes(r,r.allowRecurse?Wn+1:Wn))&&ho.push(r),pd()}function vu(r,d,w=Ko?sn+1:0){for(;wQo(w)-Qo(t));if(ho.length=0,Tn){Tn.push(...d);return}for(Tn=d,Wn=0;Wnr.id==null?1/0:r.id,Ep=(r,d)=>{const w=Qo(r)-Qo(d);if(w===0){if(r.pre&&!d.pre)return-1;if(d.pre&&!r.pre)return 1}return w};function md(r){la=!1,Ko=!0,dr.sort(Ep);try{for(sn=0;snGt(i)?i.trim():i)),p&&(x=w.map(oa))}let u,o=t[u=Ci(d)]||t[u=Ci(an(d))];!o&&v&&(o=t[u=Ci(xo(d))]),o&&zr(o,r,6,x);const c=t[u+"Once"];if(c){if(!r.emitted)r.emitted={};else if(r.emitted[u])return;r.emitted[u]=!0,zr(c,r,6,x)}}function yd(r,d,w=!1){const t=d.emitsCache,x=t.get(r);if(x!==void 0)return x;const v=r.emits;let s={},u=!1;if(!at(r)){const o=c=>{const g=yd(c,d,!0);g&&(u=!0,Yt(s,g))};!w&&d.mixins.length&&d.mixins.forEach(o),r.extends&&o(r.extends),r.mixins&&r.mixins.forEach(o)}return!v&&!u?(Ot(r)&&t.set(r,null),null):(st(v)?v.forEach(o=>s[o]=null):Yt(s,v),Ot(r)&&t.set(r,s),s)}function ai(r,d){return!r||!os(d)?!1:(d=d.slice(2).replace(/Once$/,""),vt(r,d[0].toLowerCase()+d.slice(1))||vt(r,xo(d))||vt(r,d))}let Xt=null,gd=null;function zs(r){const d=Xt;return Xt=r,gd=r&&r.type.__scopeId||null,d}function Ir(r,d=Xt,w){if(!d||r._n)return r;const t=(...x)=>{t._d&&Pu(-1);const v=zs(d);let s;try{s=r(...x)}finally{zs(v),t._d&&Pu(1)}return s};return t._n=!0,t._c=!0,t._d=!0,t}function Pi(r){const{type:d,vnode:w,proxy:t,withProxy:x,propsOptions:[v],slots:s,attrs:u,emit:o,render:c,renderCache:g,props:p,data:n,setupState:i,ctx:a,inheritAttrs:h}=r,y=zs(r);let l,f;try{if(w.shapeFlag&4){const b=x||t,j=b;l=Gr(c.call(j,b,g,p,i,n,a)),f=u}else{const b=d;l=Gr(b.length>1?b(p,{attrs:u,slots:s,emit:o}):b(p,null)),f=d.props?u:kp(u)}}catch(b){Ho.length=0,jo(b,r,1),l=ft(gr)}let m=l;if(f&&h!==!1){const b=Object.keys(f),{shapeFlag:j}=m;b.length&&j&7&&(v&&b.some(Ga)&&(f=Cp(f,v)),m=un(m,f))}return w.dirs&&(m=un(m),m.dirs=m.dirs?m.dirs.concat(w.dirs):w.dirs),w.transition&&(m.transition=w.transition),l=m,zs(y),l}function Mp(r,d=!0){let w;for(let t=0;t{let d;for(const w in r)(w==="class"||w==="style"||os(w))&&((d||(d={}))[w]=r[w]);return d},Cp=(r,d)=>{const w={};for(const t in r)(!Ga(t)||!(t.slice(9)in d))&&(w[t]=r[t]);return w};function Op(r,d,w){const{props:t,children:x,component:v}=r,{props:s,children:u,patchFlag:o}=d,c=v.emitsOptions;if(d.dirs||d.transition)return!0;if(w&&o>=0){if(o&1024)return!0;if(o&16)return t?bu(t,s,c):!!s;if(o&8){const g=d.dynamicProps;for(let p=0;pr.__isSuspense;let ca=0;const Rp={name:"Suspense",__isSuspense:!0,process(r,d,w,t,x,v,s,u,o,c){if(r==null)Lp(d,w,t,x,v,s,u,o,c);else{if(v&&v.deps>0&&!r.suspense.isInFallback){d.suspense=r.suspense,d.suspense.vnode=d,d.el=r.el;return}Ip(r,d,w,t,x,s,u,o,c)}},hydrate:Dp,create:nl,normalize:Fp},rl=Rp;function Jo(r,d){const w=r.props&&r.props[d];at(w)&&w()}function Lp(r,d,w,t,x,v,s,u,o){const{p:c,o:{createElement:g}}=o,p=g("div"),n=r.suspense=nl(r,x,t,d,p,w,v,s,u,o);c(null,n.pendingBranch=r.ssContent,p,null,t,n,v,s),n.deps>0?(Jo(r,"onPending"),Jo(r,"onFallback"),c(null,r.ssFallback,d,w,t,null,v,s),po(n,r.ssFallback)):n.resolve(!1,!0)}function Ip(r,d,w,t,x,v,s,u,{p:o,um:c,o:{createElement:g}}){const p=d.suspense=r.suspense;p.vnode=d,d.el=r.el;const n=d.ssContent,i=d.ssFallback,{activeBranch:a,pendingBranch:h,isInFallback:y,isHydrating:l}=p;if(h)p.pendingBranch=n,Kr(n,h)?(o(h,n,p.hiddenContainer,null,x,p,v,s,u),p.deps<=0?p.resolve():y&&(l||(o(a,i,w,t,x,null,v,s,u),po(p,i)))):(p.pendingId=ca++,l?(p.isHydrating=!1,p.activeBranch=h):c(h,x,p),p.deps=0,p.effects.length=0,p.hiddenContainer=g("div"),y?(o(null,n,p.hiddenContainer,null,x,p,v,s,u),p.deps<=0?p.resolve():(o(a,i,w,t,x,null,v,s,u),po(p,i))):a&&Kr(n,a)?(o(a,n,w,t,x,p,v,s,u),p.resolve(!0)):(o(null,n,p.hiddenContainer,null,x,p,v,s,u),p.deps<=0&&p.resolve()));else if(a&&Kr(n,a))o(a,n,w,t,x,p,v,s,u),po(p,n);else if(Jo(d,"onPending"),p.pendingBranch=n,n.shapeFlag&512?p.pendingId=n.component.suspenseId:p.pendingId=ca++,o(null,n,p.hiddenContainer,null,x,p,v,s,u),p.deps<=0)p.resolve();else{const{timeout:f,pendingId:m}=p;f>0?setTimeout(()=>{p.pendingId===m&&p.fallback(i)},f):f===0&&p.fallback(i)}}function nl(r,d,w,t,x,v,s,u,o,c,g=!1){const{p,m:n,um:i,n:a,o:{parentNode:h,remove:y}}=c;let l;const f=Np(r);f&&d!=null&&d.pendingBranch&&(l=d.pendingId,d.deps++);const m=r.props?Wc(r.props.timeout):void 0,b=v,j={vnode:r,parent:d,parentComponent:w,namespace:s,container:t,hiddenContainer:x,deps:0,pendingId:ca++,timeout:typeof m=="number"?m:-1,activeBranch:null,pendingBranch:null,isInFallback:!g,isHydrating:g,isUnmounted:!1,effects:[],resolve(M=!1,E=!1){const{vnode:k,activeBranch:P,pendingBranch:L,pendingId:C,effects:I,parentComponent:A,container:N}=j;let F=!1;j.isHydrating?j.isHydrating=!1:M||(F=P&&L.transition&&L.transition.mode==="out-in",F&&(P.transition.afterLeave=()=>{C===j.pendingId&&(n(L,N,v===b?a(P):v,0),ua(I))}),P&&(h(P.el)!==j.hiddenContainer&&(v=a(P)),i(P,A,j,!0)),F||n(L,N,v,0)),po(j,L),j.pendingBranch=null,j.isInFallback=!1;let B=j.parent,q=!1;for(;B;){if(B.pendingBranch){B.effects.push(...I),q=!0;break}B=B.parent}!q&&!F&&ua(I),j.effects=[],f&&d&&d.pendingBranch&&l===d.pendingId&&(d.deps--,d.deps===0&&!E&&d.resolve()),Jo(k,"onResolve")},fallback(M){if(!j.pendingBranch)return;const{vnode:E,activeBranch:k,parentComponent:P,container:L,namespace:C}=j;Jo(E,"onFallback");const I=a(k),A=()=>{j.isInFallback&&(p(null,M,L,I,P,null,C,u,o),po(j,M))},N=M.transition&&M.transition.mode==="out-in";N&&(k.transition.afterLeave=A),j.isInFallback=!0,i(k,P,null,!0),N||A()},move(M,E,k){j.activeBranch&&n(j.activeBranch,M,E,k),j.container=M},next(){return j.activeBranch&&a(j.activeBranch)},registerDep(M,E){const k=!!j.pendingBranch;k&&j.deps++;const P=M.vnode.el;M.asyncDep.catch(L=>{jo(L,M,0)}).then(L=>{if(M.isUnmounted||j.isUnmounted||j.pendingId!==M.suspenseId)return;M.asyncResolved=!0;const{vnode:C}=M;va(M,L,!1),P&&(C.el=P);const I=!P&&M.subTree.el;E(M,C,h(P||M.subTree.el),P?null:a(M.subTree),j,s,o),I&&y(I),tl(M,C.el),k&&--j.deps===0&&j.resolve()})},unmount(M,E){j.isUnmounted=!0,j.activeBranch&&i(j.activeBranch,w,M,E),j.pendingBranch&&i(j.pendingBranch,w,M,E)}};return j}function Dp(r,d,w,t,x,v,s,u,o){const c=d.suspense=nl(d,t,w,r.parentNode,document.createElement("div"),null,x,v,s,u,!0),g=o(r,c.pendingBranch=d.ssContent,w,c,v,s);return c.deps===0&&c.resolve(!1,!0),g}function Fp(r){const{shapeFlag:d,children:w}=r,t=d&32;r.ssContent=wu(t?w.default:w),r.ssFallback=t?wu(w.fallback):ft(gr)}function wu(r){let d;if(at(r)){const w=vo&&r._c;w&&(r._d=!1,Fr()),r=r(),w&&(r._d=!0,d=Hr,Yd())}return st(r)&&(r=Mp(r)),r=Gr(r),d&&!r.dynamicChildren&&(r.dynamicChildren=d.filter(w=>w!==r)),r}function xd(r,d){d&&d.pendingBranch?st(r)?d.effects.push(...r):d.effects.push(r):ua(r)}function po(r,d){r.activeBranch=d;const{vnode:w,parentComponent:t}=r;let x=d.el;for(;!x&&d.component;)d=d.component.subTree,x=d.el;w.el=x,t&&t.subTree===w&&(t.vnode.el=x,tl(t,x))}function Np(r){var d;return((d=r.props)==null?void 0:d.suspensible)!=null&&r.props.suspensible!==!1}const Up=Symbol.for("v-scx"),Bp=()=>Ht(Up);function ln(r,d){return ol(r,null,d)}const Ts={};function In(r,d,w){return ol(r,d,w)}function ol(r,d,{immediate:w,deep:t,flush:x,once:v,onTrack:s,onTrigger:u}=Lt){if(d&&v){const M=d;d=(...E)=>{M(...E),j()}}const o=Zt,c=M=>t===!0?M:Xn(M,t===!1?1:void 0);let g,p=!1,n=!1;if(fr(r)?(g=()=>r.value,p=Vs(r)):Uo(r)?(g=()=>c(r),p=!0):st(r)?(n=!0,p=r.some(M=>Uo(M)||Vs(M)),g=()=>r.map(M=>{if(fr(M))return M.value;if(Uo(M))return c(M);if(at(M))return Ln(M,o,2)})):at(r)?d?g=()=>Ln(r,o,2):g=()=>(i&&i(),zr(r,o,3,[a])):g=Vr,d&&t){const M=g;g=()=>Xn(M())}let i,a=M=>{i=m.onStop=()=>{Ln(M,o,4),i=m.onStop=void 0}},h;if(ds)if(a=Vr,d?w&&zr(d,o,3,[g(),n?[]:void 0,a]):g(),x==="sync"){const M=Bp();h=M.__watcherHandles||(M.__watcherHandles=[])}else return Vr;let y=n?new Array(r.length).fill(Ts):Ts;const l=()=>{if(!(!m.active||!m.dirty))if(d){const M=m.run();(t||p||(n?M.some((E,k)=>Dn(E,y[k])):Dn(M,y)))&&(i&&i(),zr(d,o,3,[M,y===Ts?void 0:n&&y[0]===Ts?[]:y,a]),y=M)}else m.run()};l.allowRecurse=!!d;let f;x==="sync"?f=l:x==="post"?f=()=>sr(l,o&&o.suspense):(l.pre=!0,o&&(l.id=o.uid),f=()=>ii(l));const m=new qa(g,Vr,f),b=Xh(),j=()=>{m.stop(),b&&Va(b.effects,m)};return d?w?l():y=m.run():x==="post"?sr(m.run.bind(m),o&&o.suspense):m.run(),h&&h.push(j),j}function Gp(r,d,w){const t=this.proxy,x=Gt(r)?r.includes(".")?jd(t,r):()=>t[r]:r.bind(t,t);let v;at(d)?v=d:(v=d.handler,w=d);const s=Qn(this),u=ol(x,v.bind(t),w);return s(),u}function jd(r,d){const w=d.split(".");return()=>{let t=r;for(let x=0;x0){if(w>=d)return r;w++}if(t=t||new Set,t.has(r))return r;if(t.add(r),fr(r))Xn(r.value,d,w,t);else if(st(r))for(let x=0;x{Xn(x,d,w,t)});else if(Hc(r))for(const x in r)Xn(r[x],d,w,t);return r}function T_(r,d){if(Xt===null)return r;const w=ui(Xt)||Xt.proxy,t=r.dirs||(r.dirs=[]);for(let x=0;x{r.isMounted=!0}),ls(()=>{r.isUnmounting=!0}),r}const Br=[Function,Array],Sd={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:Br,onEnter:Br,onAfterEnter:Br,onEnterCancelled:Br,onBeforeLeave:Br,onLeave:Br,onAfterLeave:Br,onLeaveCancelled:Br,onBeforeAppear:Br,onAppear:Br,onAfterAppear:Br,onAppearCancelled:Br},Hp={name:"BaseTransition",props:Sd,setup(r,{slots:d}){const w=So(),t=Vp();return()=>{const x=d.default&&Td(d.default(),!0);if(!x||!x.length)return;let v=x[0];if(x.length>1){for(const n of x)if(n.type!==gr){v=n;break}}const s=bt(r),{mode:u}=s;if(t.isLeaving)return Ai(v);const o=xu(v);if(!o)return Ai(v);const c=da(o,s,t,w);Ws(o,c);const g=w.subTree,p=g&&xu(g);if(p&&p.type!==gr&&!Kr(o,p)){const n=da(p,s,t,w);if(Ws(p,n),u==="out-in")return t.isLeaving=!0,n.afterLeave=()=>{t.isLeaving=!1,w.update.active!==!1&&(w.effect.dirty=!0,w.update())},Ai(v);u==="in-out"&&o.type!==gr&&(n.delayLeave=(i,a,h)=>{const y=Ed(t,p);y[String(p.key)]=p,i[Mn]=()=>{a(),i[Mn]=void 0,delete c.delayedLeave},c.delayedLeave=h})}return v}}},zp=Hp;function Ed(r,d){const{leavingVNodes:w}=r;let t=w.get(d.type);return t||(t=Object.create(null),w.set(d.type,t)),t}function da(r,d,w,t){const{appear:x,mode:v,persisted:s=!1,onBeforeEnter:u,onEnter:o,onAfterEnter:c,onEnterCancelled:g,onBeforeLeave:p,onLeave:n,onAfterLeave:i,onLeaveCancelled:a,onBeforeAppear:h,onAppear:y,onAfterAppear:l,onAppearCancelled:f}=d,m=String(r.key),b=Ed(w,r),j=(k,P)=>{k&&zr(k,t,9,P)},M=(k,P)=>{const L=P[1];j(k,P),st(k)?k.every(C=>C.length<=1)&&L():k.length<=1&&L()},E={mode:v,persisted:s,beforeEnter(k){let P=u;if(!w.isMounted)if(x)P=h||u;else return;k[Mn]&&k[Mn](!0);const L=b[m];L&&Kr(r,L)&&L.el[Mn]&&L.el[Mn](),j(P,[k])},enter(k){let P=o,L=c,C=g;if(!w.isMounted)if(x)P=y||o,L=l||c,C=f||g;else return;let I=!1;const A=k[Ms]=N=>{I||(I=!0,N?j(C,[k]):j(L,[k]),E.delayedLeave&&E.delayedLeave(),k[Ms]=void 0)};P?M(P,[k,A]):A()},leave(k,P){const L=String(r.key);if(k[Ms]&&k[Ms](!0),w.isUnmounting)return P();j(p,[k]);let C=!1;const I=k[Mn]=A=>{C||(C=!0,P(),A?j(a,[k]):j(i,[k]),k[Mn]=void 0,b[L]===r&&delete b[L])};b[L]=r,n?M(n,[k,I]):I()},clone(k){return da(k,d,w,t)}};return E}function Ai(r){if(as(r))return r=un(r),r.children=null,r}function xu(r){if(!as(r))return r;const{shapeFlag:d,children:w}=r;if(w){if(d&16)return w[0];if(d&32&&at(w.default))return w.default()}}function Ws(r,d){r.shapeFlag&6&&r.component?Ws(r.component.subTree,d):r.shapeFlag&128?(r.ssContent.transition=d.clone(r.ssContent),r.ssFallback.transition=d.clone(r.ssFallback)):r.transition=d}function Td(r,d=!1,w){let t=[],x=0;for(let v=0;v1)for(let v=0;v!!r.type.__asyncLoader;/*! #__NO_SIDE_EFFECTS__ */function ht(r){at(r)&&(r={loader:r});const{loader:d,loadingComponent:w,errorComponent:t,delay:x=200,timeout:v,suspensible:s=!0,onError:u}=r;let o=null,c,g=0;const p=()=>(g++,o=null,n()),n=()=>{let i;return o||(i=o=d().catch(a=>{if(a=a instanceof Error?a:new Error(String(a)),u)return new Promise((h,y)=>{u(a,()=>h(p()),()=>y(a),g+1)});throw a}).then(a=>i!==o&&o?o:(a&&(a.__esModule||a[Symbol.toStringTag]==="Module")&&(a=a.default),c=a,a)))};return hr({name:"AsyncComponentWrapper",__asyncLoader:n,get __asyncResolved(){return c},setup(){const i=Zt;if(c)return()=>Ri(c,i);const a=f=>{o=null,jo(f,i,13,!t)};if(s&&i.suspense||ds)return n().then(f=>()=>Ri(f,i)).catch(f=>(a(f),()=>t?ft(t,{error:f}):null));const h=mt(!1),y=mt(),l=mt(!!x);return x&&setTimeout(()=>{l.value=!1},x),v!=null&&setTimeout(()=>{if(!h.value&&!y.value){const f=new Error(`Async component timed out after ${v}ms.`);a(f),y.value=f}},v),n().then(()=>{h.value=!0,i.parent&&as(i.parent.vnode)&&(i.parent.effect.dirty=!0,ii(i.parent.update))}).catch(f=>{a(f),y.value=f}),()=>{if(h.value&&c)return Ri(c,i);if(y.value&&t)return ft(t,{error:y.value});if(w&&!l.value)return ft(w)}}})}function Ri(r,d){const{ref:w,props:t,children:x,ce:v}=d.vnode,s=ft(r,t,x);return s.ref=w,s.ce=v,delete d.vnode.ce,s}const as=r=>r.type.__isKeepAlive,Wp={name:"KeepAlive",__isKeepAlive:!0,props:{include:[String,RegExp,Array],exclude:[String,RegExp,Array],max:[String,Number]},setup(r,{slots:d}){const w=So(),t=w.ctx;if(!t.renderer)return()=>{const f=d.default&&d.default();return f&&f.length===1?f[0]:f};const x=new Map,v=new Set;let s=null;const u=w.suspense,{renderer:{p:o,m:c,um:g,o:{createElement:p}}}=t,n=p("div");t.activate=(f,m,b,j,M)=>{const E=f.component;c(f,m,b,0,u),o(E.vnode,f,m,b,E,u,j,f.slotScopeIds,M),sr(()=>{E.isDeactivated=!1,E.a&&fo(E.a);const k=f.props&&f.props.onVnodeMounted;k&&vr(k,E.parent,f)},u)},t.deactivate=f=>{const m=f.component;c(f,n,null,1,u),sr(()=>{m.da&&fo(m.da);const b=f.props&&f.props.onVnodeUnmounted;b&&vr(b,m.parent,f),m.isDeactivated=!0},u)};function i(f){Li(f),g(f,w,u,!0)}function a(f){x.forEach((m,b)=>{const j=ba(m.type);j&&(!f||!f(j))&&h(b)})}function h(f){const m=x.get(f);!s||!Kr(m,s)?i(m):s&&Li(s),x.delete(f),v.delete(f)}In(()=>[r.include,r.exclude],([f,m])=>{f&&a(b=>Fo(f,b)),m&&a(b=>!Fo(m,b))},{flush:"post",deep:!0});let y=null;const l=()=>{y!=null&&x.set(y,Ii(w.subTree))};return Qr(l),Od(l),ls(()=>{x.forEach(f=>{const{subTree:m,suspense:b}=w,j=Ii(m);if(f.type===j.type&&f.key===j.key){Li(j);const M=j.component.da;M&&sr(M,b);return}i(f)})}),()=>{if(y=null,!d.default)return s=null;const f=d.default(),m=f[0];if(f.length>1)return s=null,f;if(!bo(m)||!(m.shapeFlag&4)&&!(m.shapeFlag&128))return s=null,m;let b=Ii(m);const j=b.type,M=ba(Kn(b)?b.type.__asyncResolved||{}:j),{include:E,exclude:k,max:P}=r;if(E&&(!M||!Fo(E,M))||k&&M&&Fo(k,M))return s=b,m;const L=b.key==null?j:b.key,C=x.get(L);return b.el&&(b=un(b),m.shapeFlag&128&&(m.ssContent=b)),y=L,C?(b.el=C.el,b.component=C.component,b.transition&&Ws(b,b.transition),b.shapeFlag|=512,v.delete(L),v.add(L)):(v.add(L),P&&v.size>parseInt(P,10)&&h(v.values().next().value)),b.shapeFlag|=256,s=b,wd(m.type)?m:b}}},qp=Wp;function Fo(r,d){return st(r)?r.some(w=>Fo(w,d)):Gt(r)?r.split(",").includes(d):Ih(r)?r.test(d):!1}function Md(r,d){Cd(r,"a",d)}function kd(r,d){Cd(r,"da",d)}function Cd(r,d,w=Zt){const t=r.__wdc||(r.__wdc=()=>{let x=w;for(;x;){if(x.isDeactivated)return;x=x.parent}return r()});if(li(d,t,w),w){let x=w.parent;for(;x&&x.parent;)as(x.parent.vnode)&&Xp(t,d,w,x),x=x.parent}}function Xp(r,d,w,t){const x=li(d,r,t,!0);us(()=>{Va(t[d],x)},w)}function Li(r){r.shapeFlag&=-257,r.shapeFlag&=-513}function Ii(r){return r.shapeFlag&128?r.ssContent:r}function li(r,d,w=Zt,t=!1){if(w){const x=w[r]||(w[r]=[]),v=d.__weh||(d.__weh=(...s)=>{if(w.isUnmounted)return;Fn();const u=Qn(w),o=zr(d,w,r,s);return u(),Nn(),o});return t?x.unshift(v):x.push(v),v}}const mn=r=>(d,w=Zt)=>(!ds||r==="sp")&&li(r,(...t)=>d(...t),w),Yp=mn("bm"),Qr=mn("m"),$p=mn("bu"),Od=mn("u"),ls=mn("bum"),us=mn("um"),Zp=mn("sp"),Kp=mn("rtg"),Qp=mn("rtc");function Pd(r,d=Zt){li("ec",r,d)}function M_(r,d,w,t){let x;const v=w;if(st(r)||Gt(r)){x=new Array(r.length);for(let s=0,u=r.length;sd(s,u,void 0,v));else{const s=Object.keys(r);x=new Array(s.length);for(let u=0,o=s.length;ubo(d)?!(d.type===gr||d.type===yr&&!Ad(d.children)):!0)?r:null}const fa=r=>r?Qd(r)?ui(r)||r.proxy:fa(r.parent):null,Go=Yt(Object.create(null),{$:r=>r,$el:r=>r.vnode.el,$data:r=>r.data,$props:r=>r.props,$attrs:r=>r.attrs,$slots:r=>r.slots,$refs:r=>r.refs,$parent:r=>fa(r.parent),$root:r=>fa(r.root),$emit:r=>r.emit,$options:r=>sl(r),$forceUpdate:r=>r.f||(r.f=()=>{r.effect.dirty=!0,ii(r.update)}),$nextTick:r=>r.n||(r.n=Ur.bind(r.proxy)),$watch:r=>Gp.bind(r)}),Di=(r,d)=>r!==Lt&&!r.__isScriptSetup&&vt(r,d),Jp={get({_:r},d){if(d==="__v_skip")return!0;const{ctx:w,setupState:t,data:x,props:v,accessCache:s,type:u,appContext:o}=r;let c;if(d[0]!=="$"){const i=s[d];if(i!==void 0)switch(i){case 1:return t[d];case 2:return x[d];case 4:return w[d];case 3:return v[d]}else{if(Di(t,d))return s[d]=1,t[d];if(x!==Lt&&vt(x,d))return s[d]=2,x[d];if((c=r.propsOptions[0])&&vt(c,d))return s[d]=3,v[d];if(w!==Lt&&vt(w,d))return s[d]=4,w[d];ha&&(s[d]=0)}}const g=Go[d];let p,n;if(g)return d==="$attrs"&&br(r.attrs,"get",""),g(r);if((p=u.__cssModules)&&(p=p[d]))return p;if(w!==Lt&&vt(w,d))return s[d]=4,w[d];if(n=o.config.globalProperties,vt(n,d))return n[d]},set({_:r},d,w){const{data:t,setupState:x,ctx:v}=r;return Di(x,d)?(x[d]=w,!0):t!==Lt&&vt(t,d)?(t[d]=w,!0):vt(r.props,d)||d[0]==="$"&&d.slice(1)in r?!1:(v[d]=w,!0)},has({_:{data:r,setupState:d,accessCache:w,ctx:t,appContext:x,propsOptions:v}},s){let u;return!!w[s]||r!==Lt&&vt(r,s)||Di(d,s)||(u=v[0])&&vt(u,s)||vt(t,s)||vt(Go,s)||vt(x.config.globalProperties,s)},defineProperty(r,d,w){return w.get!=null?r._.accessCache[d]=0:vt(w,"value")&&this.set(r,d,w.value,null),Reflect.defineProperty(r,d,w)}};function C_(){return em().slots}function em(){const r=So();return r.setupContext||(r.setupContext=ef(r))}function ju(r){return st(r)?r.reduce((d,w)=>(d[w]=null,d),{}):r}function O_(r){const d=So();let w=r();return ga(),Ha(w)&&(w=w.catch(t=>{throw Qn(d),t})),[w,()=>Qn(d)]}let ha=!0;function tm(r){const d=sl(r),w=r.proxy,t=r.ctx;ha=!1,d.beforeCreate&&Su(d.beforeCreate,r,"bc");const{data:x,computed:v,methods:s,watch:u,provide:o,inject:c,created:g,beforeMount:p,mounted:n,beforeUpdate:i,updated:a,activated:h,deactivated:y,beforeDestroy:l,beforeUnmount:f,destroyed:m,unmounted:b,render:j,renderTracked:M,renderTriggered:E,errorCaptured:k,serverPrefetch:P,expose:L,inheritAttrs:C,components:I,directives:A,filters:N}=d;if(c&&rm(c,t,null),s)for(const q in s){const V=s[q];at(V)&&(t[q]=V.bind(w))}if(x){const q=x.call(w,w);Ot(q)&&(r.data=Un(q))}if(ha=!0,v)for(const q in v){const V=v[q],H=at(V)?V.bind(w,w):at(V.get)?V.get.bind(w,w):Vr,K=!at(V)&&at(V.set)?V.set.bind(w):Vr,ee=jt({get:H,set:K});Object.defineProperty(t,q,{enumerable:!0,configurable:!0,get:()=>ee.value,set:ue=>ee.value=ue})}if(u)for(const q in u)Rd(u[q],t,w,q);if(o){const q=at(o)?o.call(w):o;Reflect.ownKeys(q).forEach(V=>{Wr(V,q[V])})}g&&Su(g,r,"c");function B(q,V){st(V)?V.forEach(H=>q(H.bind(w))):V&&q(V.bind(w))}if(B(Yp,p),B(Qr,n),B($p,i),B(Od,a),B(Md,h),B(kd,y),B(Pd,k),B(Qp,M),B(Kp,E),B(ls,f),B(us,b),B(Zp,P),st(L))if(L.length){const q=r.exposed||(r.exposed={});L.forEach(V=>{Object.defineProperty(q,V,{get:()=>w[V],set:H=>w[V]=H})})}else r.exposed||(r.exposed={});j&&r.render===Vr&&(r.render=j),C!=null&&(r.inheritAttrs=C),I&&(r.components=I),A&&(r.directives=A)}function rm(r,d,w=Vr){st(r)&&(r=pa(r));for(const t in r){const x=r[t];let v;Ot(x)?"default"in x?v=Ht(x.from||t,x.default,!0):v=Ht(x.from||t):v=Ht(x),fr(v)?Object.defineProperty(d,t,{enumerable:!0,configurable:!0,get:()=>v.value,set:s=>v.value=s}):d[t]=v}}function Su(r,d,w){zr(st(r)?r.map(t=>t.bind(d.proxy)):r.bind(d.proxy),d,w)}function Rd(r,d,w,t){const x=t.includes(".")?jd(w,t):()=>w[t];if(Gt(r)){const v=d[r];at(v)&&In(x,v)}else if(at(r))In(x,r.bind(w));else if(Ot(r))if(st(r))r.forEach(v=>Rd(v,d,w,t));else{const v=at(r.handler)?r.handler.bind(w):d[r.handler];at(v)&&In(x,v,r)}}function sl(r){const d=r.type,{mixins:w,extends:t}=d,{mixins:x,optionsCache:v,config:{optionMergeStrategies:s}}=r.appContext,u=v.get(d);let o;return u?o=u:!x.length&&!w&&!t?o=d:(o={},x.length&&x.forEach(c=>qs(o,c,s,!0)),qs(o,d,s)),Ot(d)&&v.set(d,o),o}function qs(r,d,w,t=!1){const{mixins:x,extends:v}=d;v&&qs(r,v,w,!0),x&&x.forEach(s=>qs(r,s,w,!0));for(const s in d)if(!(t&&s==="expose")){const u=nm[s]||w&&w[s];r[s]=u?u(r[s],d[s]):d[s]}return r}const nm={data:Eu,props:Tu,emits:Tu,methods:No,computed:No,beforeCreate:mr,created:mr,beforeMount:mr,mounted:mr,beforeUpdate:mr,updated:mr,beforeDestroy:mr,beforeUnmount:mr,destroyed:mr,unmounted:mr,activated:mr,deactivated:mr,errorCaptured:mr,serverPrefetch:mr,components:No,directives:No,watch:sm,provide:Eu,inject:om};function Eu(r,d){return d?r?function(){return Yt(at(r)?r.call(this,this):r,at(d)?d.call(this,this):d)}:d:r}function om(r,d){return No(pa(r),pa(d))}function pa(r){if(st(r)){const d={};for(let w=0;w1)return w&&at(d)?d.call(t&&t.proxy):d}}function Id(){return!!(Zt||Xt||mo)}const Dd={},Fd=()=>Object.create(Dd),Nd=r=>Object.getPrototypeOf(r)===Dd;function lm(r,d,w,t=!1){const x={},v=Fd();r.propsDefaults=Object.create(null),Ud(r,d,x,v);for(const s in r.propsOptions[0])s in x||(x[s]=void 0);w?r.props=t?x:is(x):r.type.props?r.props=x:r.props=v,r.attrs=v}function um(r,d,w,t){const{props:x,attrs:v,vnode:{patchFlag:s}}=r,u=bt(x),[o]=r.propsOptions;let c=!1;if((t||s>0)&&!(s&16)){if(s&8){const g=r.vnode.dynamicProps;for(let p=0;p{o=!0;const[n,i]=Bd(p,d,!0);Yt(s,n),i&&u.push(...i)};!w&&d.mixins.length&&d.mixins.forEach(g),r.extends&&g(r.extends),r.mixins&&r.mixins.forEach(g)}if(!v&&!o)return Ot(r)&&t.set(r,lo),lo;if(st(v))for(let g=0;g-1,i[1]=h<0||a-1||vt(i,"default"))&&u.push(p)}}}const c=[s,u];return Ot(r)&&t.set(r,c),c}function Mu(r){return r[0]!=="$"&&!co(r)}function ku(r){return r===null?"null":typeof r=="function"?r.name||"":typeof r=="object"&&r.constructor&&r.constructor.name||""}function Cu(r,d){return ku(r)===ku(d)}function Ou(r,d){return st(d)?d.findIndex(w=>Cu(w,r)):at(d)&&Cu(d,r)?0:-1}const Gd=r=>r[0]==="_"||r==="$stable",il=r=>st(r)?r.map(Gr):[Gr(r)],cm=(r,d,w)=>{if(d._n)return d;const t=Ir((...x)=>il(d(...x)),w);return t._c=!1,t},Vd=(r,d,w)=>{const t=r._ctx;for(const x in r){if(Gd(x))continue;const v=r[x];if(at(v))d[x]=cm(x,v,t);else if(v!=null){const s=il(v);d[x]=()=>s}}},Hd=(r,d)=>{const w=il(d);r.slots.default=()=>w},dm=(r,d)=>{const w=r.slots=Fd();if(r.vnode.shapeFlag&32){const t=d._;t?(Yt(w,d),zc(w,"_",t)):Vd(d,w)}else d&&Hd(r,d)},fm=(r,d,w)=>{const{vnode:t,slots:x}=r;let v=!0,s=Lt;if(t.shapeFlag&32){const u=d._;u?w&&u===1?v=!1:(Yt(x,d),!w&&u===1&&delete x._):(v=!d.$stable,Vd(d,x)),s=d}else d&&(Hd(r,d),s={default:1});if(v)for(const u in x)!Gd(u)&&s[u]==null&&delete x[u]};function Xs(r,d,w,t,x=!1){if(st(r)){r.forEach((n,i)=>Xs(n,d&&(st(d)?d[i]:d),w,t,x));return}if(Kn(t)&&!x)return;const v=t.shapeFlag&4?ui(t.component)||t.component.proxy:t.el,s=x?null:v,{i:u,r:o}=r,c=d&&d.r,g=u.refs===Lt?u.refs={}:u.refs,p=u.setupState;if(c!=null&&c!==o&&(Gt(c)?(g[c]=null,vt(p,c)&&(p[c]=null)):fr(c)&&(c.value=null)),at(o))Ln(o,u,12,[s,g]);else{const n=Gt(o),i=fr(o);if(n||i){const a=()=>{if(r.f){const h=n?vt(p,o)?p[o]:g[o]:o.value;x?st(h)&&Va(h,v):st(h)?h.includes(v)||h.push(v):n?(g[o]=[v],vt(p,o)&&(p[o]=g[o])):(o.value=[v],r.k&&(g[r.k]=o.value))}else n?(g[o]=s,vt(p,o)&&(p[o]=s)):i&&(o.value=s,r.k&&(g[r.k]=s))};s?(a.id=-1,sr(a,w)):a()}}}let xn=!1;const hm=r=>r.namespaceURI.includes("svg")&&r.tagName!=="foreignObject",pm=r=>r.namespaceURI.includes("MathML"),ks=r=>{if(hm(r))return"svg";if(pm(r))return"mathml"},Cs=r=>r.nodeType===8;function mm(r){const{mt:d,p:w,o:{patchProp:t,createText:x,nextSibling:v,parentNode:s,remove:u,insert:o,createComment:c}}=r,g=(m,b)=>{if(!b.hasChildNodes()){w(null,m,b),Hs(),b._vnode=m;return}xn=!1,p(b.firstChild,m,null,null,null),Hs(),b._vnode=m,xn&&console.error("Hydration completed but contains mismatches.")},p=(m,b,j,M,E,k=!1)=>{k=k||!!b.dynamicChildren;const P=Cs(m)&&m.data==="[",L=()=>h(m,b,j,M,E,P),{type:C,ref:I,shapeFlag:A,patchFlag:N}=b;let F=m.nodeType;b.el=m,N===-2&&(k=!1,b.dynamicChildren=null);let B=null;switch(C){case go:F!==3?b.children===""?(o(b.el=x(""),s(m),m),B=m):B=L():(m.data!==b.children&&(xn=!0,m.data=b.children),B=v(m));break;case gr:f(m)?(B=v(m),l(b.el=m.content.firstChild,m,j)):F!==8||P?B=L():B=v(m);break;case Vo:if(P&&(m=v(m),F=m.nodeType),F===1||F===3){B=m;const q=!b.children.length;for(let V=0;V{k=k||!!b.dynamicChildren;const{type:P,props:L,patchFlag:C,shapeFlag:I,dirs:A,transition:N}=b,F=P==="input"||P==="option";if(F||C!==-1){A&&on(b,null,j,"created");let B=!1;if(f(m)){B=Wd(M,N)&&j&&j.vnode.props&&j.vnode.props.appear;const V=m.content.firstChild;B&&N.beforeEnter(V),l(V,m,j),b.el=m=V}if(I&16&&!(L&&(L.innerHTML||L.textContent))){let V=i(m.firstChild,b,m,j,M,E,k);for(;V;){xn=!0;const H=V;V=V.nextSibling,u(H)}}else I&8&&m.textContent!==b.children&&(xn=!0,m.textContent=b.children);if(L)if(F||!k||C&48)for(const V in L)(F&&(V.endsWith("value")||V==="indeterminate")||os(V)&&!co(V)||V[0]===".")&&t(m,V,null,L[V],void 0,void 0,j);else L.onClick&&t(m,"onClick",null,L.onClick,void 0,void 0,j);let q;(q=L&&L.onVnodeBeforeMount)&&vr(q,j,b),A&&on(b,null,j,"beforeMount"),((q=L&&L.onVnodeMounted)||A||B)&&xd(()=>{q&&vr(q,j,b),B&&N.enter(m),A&&on(b,null,j,"mounted")},M)}return m.nextSibling},i=(m,b,j,M,E,k,P)=>{P=P||!!b.dynamicChildren;const L=b.children,C=L.length;for(let I=0;I{const{slotScopeIds:P}=b;P&&(E=E?E.concat(P):P);const L=s(m),C=i(v(m),b,L,j,M,E,k);return C&&Cs(C)&&C.data==="]"?v(b.anchor=C):(xn=!0,o(b.anchor=c("]"),L,C),C)},h=(m,b,j,M,E,k)=>{if(xn=!0,b.el=null,k){const C=y(m);for(;;){const I=v(m);if(I&&I!==C)u(I);else break}}const P=v(m),L=s(m);return u(m),w(null,b,L,P,j,M,ks(L),E),P},y=(m,b="[",j="]")=>{let M=0;for(;m;)if(m=v(m),m&&Cs(m)&&(m.data===b&&M++,m.data===j)){if(M===0)return v(m);M--}return m},l=(m,b,j)=>{const M=b.parentNode;M&&M.replaceChild(m,b);let E=j;for(;E;)E.vnode.el===b&&(E.vnode.el=E.subTree.el=m),E=E.parent},f=m=>m.nodeType===1&&m.tagName.toLowerCase()==="template";return[g,p]}const sr=xd;function ym(r){return zd(r)}function gm(r){return zd(r,mm)}function zd(r,d){const w=qc();w.__VUE__=!0;const{insert:t,remove:x,patchProp:v,createElement:s,createText:u,createComment:o,setText:c,setElementText:g,parentNode:p,nextSibling:n,setScopeId:i=Vr,insertStaticContent:a}=r,h=(Z,z,te,le=null,me=null,de=null,ye=void 0,ge=null,Me=!!z.dynamicChildren)=>{if(Z===z)return;Z&&!Kr(Z,z)&&(le=$(Z),ue(Z,me,de,!0),Z=null),z.patchFlag===-2&&(Me=!1,z.dynamicChildren=null);const{type:be,ref:Ie,shapeFlag:De}=z;switch(be){case go:y(Z,z,te,le);break;case gr:l(Z,z,te,le);break;case Vo:Z==null&&f(z,te,le,ye);break;case yr:I(Z,z,te,le,me,de,ye,ge,Me);break;default:De&1?j(Z,z,te,le,me,de,ye,ge,Me):De&6?A(Z,z,te,le,me,de,ye,ge,Me):(De&64||De&128)&&be.process(Z,z,te,le,me,de,ye,ge,Me,ce)}Ie!=null&&me&&Xs(Ie,Z&&Z.ref,de,z||Z,!z)},y=(Z,z,te,le)=>{if(Z==null)t(z.el=u(z.children),te,le);else{const me=z.el=Z.el;z.children!==Z.children&&c(me,z.children)}},l=(Z,z,te,le)=>{Z==null?t(z.el=o(z.children||""),te,le):z.el=Z.el},f=(Z,z,te,le)=>{[Z.el,Z.anchor]=a(Z.children,z,te,le,Z.el,Z.anchor)},m=({el:Z,anchor:z},te,le)=>{let me;for(;Z&&Z!==z;)me=n(Z),t(Z,te,le),Z=me;t(z,te,le)},b=({el:Z,anchor:z})=>{let te;for(;Z&&Z!==z;)te=n(Z),x(Z),Z=te;x(z)},j=(Z,z,te,le,me,de,ye,ge,Me)=>{z.type==="svg"?ye="svg":z.type==="math"&&(ye="mathml"),Z==null?M(z,te,le,me,de,ye,ge,Me):P(Z,z,me,de,ye,ge,Me)},M=(Z,z,te,le,me,de,ye,ge)=>{let Me,be;const{props:Ie,shapeFlag:De,transition:Le,dirs:Ne}=Z;if(Me=Z.el=s(Z.type,de,Ie&&Ie.is,Ie),De&8?g(Me,Z.children):De&16&&k(Z.children,Me,null,le,me,Fi(Z,de),ye,ge),Ne&&on(Z,null,le,"created"),E(Me,Z,Z.scopeId,ye,le),Ie){for(const we in Ie)we!=="value"&&!co(we)&&v(Me,we,null,Ie[we],de,Z.children,le,me,W);"value"in Ie&&v(Me,"value",null,Ie.value,de),(be=Ie.onVnodeBeforeMount)&&vr(be,le,Z)}Ne&&on(Z,null,le,"beforeMount");const Be=Wd(me,Le);Be&&Le.beforeEnter(Me),t(Me,z,te),((be=Ie&&Ie.onVnodeMounted)||Be||Ne)&&sr(()=>{be&&vr(be,le,Z),Be&&Le.enter(Me),Ne&&on(Z,null,le,"mounted")},me)},E=(Z,z,te,le,me)=>{if(te&&i(Z,te),le)for(let de=0;de{for(let be=Me;be{const ge=z.el=Z.el;let{patchFlag:Me,dynamicChildren:be,dirs:Ie}=z;Me|=Z.patchFlag&16;const De=Z.props||Lt,Le=z.props||Lt;let Ne;if(te&&Bn(te,!1),(Ne=Le.onVnodeBeforeUpdate)&&vr(Ne,te,z,Z),Ie&&on(z,Z,te,"beforeUpdate"),te&&Bn(te,!0),be?L(Z.dynamicChildren,be,ge,te,le,Fi(z,me),de):ye||V(Z,z,ge,null,te,le,Fi(z,me),de,!1),Me>0){if(Me&16)C(ge,z,De,Le,te,le,me);else if(Me&2&&De.class!==Le.class&&v(ge,"class",null,Le.class,me),Me&4&&v(ge,"style",De.style,Le.style,me),Me&8){const Be=z.dynamicProps;for(let we=0;we{Ne&&vr(Ne,te,z,Z),Ie&&on(z,Z,te,"updated")},le)},L=(Z,z,te,le,me,de,ye)=>{for(let ge=0;ge{if(te!==le){if(te!==Lt)for(const ge in te)!co(ge)&&!(ge in le)&&v(Z,ge,te[ge],null,ye,z.children,me,de,W);for(const ge in le){if(co(ge))continue;const Me=le[ge],be=te[ge];Me!==be&&ge!=="value"&&v(Z,ge,be,Me,ye,z.children,me,de,W)}"value"in le&&v(Z,"value",te.value,le.value,ye)}},I=(Z,z,te,le,me,de,ye,ge,Me)=>{const be=z.el=Z?Z.el:u(""),Ie=z.anchor=Z?Z.anchor:u("");let{patchFlag:De,dynamicChildren:Le,slotScopeIds:Ne}=z;Ne&&(ge=ge?ge.concat(Ne):Ne),Z==null?(t(be,te,le),t(Ie,te,le),k(z.children||[],te,Ie,me,de,ye,ge,Me)):De>0&&De&64&&Le&&Z.dynamicChildren?(L(Z.dynamicChildren,Le,te,me,de,ye,ge),(z.key!=null||me&&z===me.subTree)&&qd(Z,z,!0)):V(Z,z,te,Ie,me,de,ye,ge,Me)},A=(Z,z,te,le,me,de,ye,ge,Me)=>{z.slotScopeIds=ge,Z==null?z.shapeFlag&512?me.ctx.activate(z,te,le,ye,Me):N(z,te,le,me,de,ye,Me):F(Z,z,Me)},N=(Z,z,te,le,me,de,ye)=>{const ge=Z.component=Em(Z,le,me);if(as(Z)&&(ge.ctx.renderer=ce),Tm(ge),ge.asyncDep){if(me&&me.registerDep(ge,B),!Z.el){const Me=ge.subTree=ft(gr);l(null,Me,z,te)}}else B(ge,Z,z,te,me,de,ye)},F=(Z,z,te)=>{const le=z.component=Z.component;if(Op(Z,z,te))if(le.asyncDep&&!le.asyncResolved){q(le,z,te);return}else le.next=z,Sp(le.update),le.effect.dirty=!0,le.update();else z.el=Z.el,le.vnode=z},B=(Z,z,te,le,me,de,ye)=>{const ge=()=>{if(Z.isMounted){let{next:Ie,bu:De,u:Le,parent:Ne,vnode:Be}=Z;{const se=Xd(Z);if(se){Ie&&(Ie.el=Be.el,q(Z,Ie,ye)),se.asyncDep.then(()=>{Z.isUnmounted||ge()});return}}let we=Ie,Re;Bn(Z,!1),Ie?(Ie.el=Be.el,q(Z,Ie,ye)):Ie=Be,De&&fo(De),(Re=Ie.props&&Ie.props.onVnodeBeforeUpdate)&&vr(Re,Ne,Ie,Be),Bn(Z,!0);const Ee=Pi(Z),re=Z.subTree;Z.subTree=Ee,h(re,Ee,p(re.el),$(re),Z,me,de),Ie.el=Ee.el,we===null&&tl(Z,Ee.el),Le&&sr(Le,me),(Re=Ie.props&&Ie.props.onVnodeUpdated)&&sr(()=>vr(Re,Ne,Ie,Be),me)}else{let Ie;const{el:De,props:Le}=z,{bm:Ne,m:Be,parent:we}=Z,Re=Kn(z);if(Bn(Z,!1),Ne&&fo(Ne),!Re&&(Ie=Le&&Le.onVnodeBeforeMount)&&vr(Ie,we,z),Bn(Z,!0),De&&pe){const Ee=()=>{Z.subTree=Pi(Z),pe(De,Z.subTree,Z,me,null)};Re?z.type.__asyncLoader().then(()=>!Z.isUnmounted&&Ee()):Ee()}else{const Ee=Z.subTree=Pi(Z);h(null,Ee,te,le,Z,me,de),z.el=Ee.el}if(Be&&sr(Be,me),!Re&&(Ie=Le&&Le.onVnodeMounted)){const Ee=z;sr(()=>vr(Ie,we,Ee),me)}(z.shapeFlag&256||we&&Kn(we.vnode)&&we.vnode.shapeFlag&256)&&Z.a&&sr(Z.a,me),Z.isMounted=!0,z=te=le=null}},Me=Z.effect=new qa(ge,Vr,()=>ii(be),Z.scope),be=Z.update=()=>{Me.dirty&&Me.run()};be.id=Z.uid,Bn(Z,!0),be()},q=(Z,z,te)=>{z.component=Z;const le=Z.vnode.props;Z.vnode=z,Z.next=null,um(Z,z.props,le,te),fm(Z,z.children,te),Fn(),vu(Z),Nn()},V=(Z,z,te,le,me,de,ye,ge,Me=!1)=>{const be=Z&&Z.children,Ie=Z?Z.shapeFlag:0,De=z.children,{patchFlag:Le,shapeFlag:Ne}=z;if(Le>0){if(Le&128){K(be,De,te,le,me,de,ye,ge,Me);return}else if(Le&256){H(be,De,te,le,me,de,ye,ge,Me);return}}Ne&8?(Ie&16&&W(be,me,de),De!==be&&g(te,De)):Ie&16?Ne&16?K(be,De,te,le,me,de,ye,ge,Me):W(be,me,de,!0):(Ie&8&&g(te,""),Ne&16&&k(De,te,le,me,de,ye,ge,Me))},H=(Z,z,te,le,me,de,ye,ge,Me)=>{Z=Z||lo,z=z||lo;const be=Z.length,Ie=z.length,De=Math.min(be,Ie);let Le;for(Le=0;LeIe?W(Z,me,de,!0,!1,De):k(z,te,le,me,de,ye,ge,Me,De)},K=(Z,z,te,le,me,de,ye,ge,Me)=>{let be=0;const Ie=z.length;let De=Z.length-1,Le=Ie-1;for(;be<=De&&be<=Le;){const Ne=Z[be],Be=z[be]=Me?kn(z[be]):Gr(z[be]);if(Kr(Ne,Be))h(Ne,Be,te,null,me,de,ye,ge,Me);else break;be++}for(;be<=De&&be<=Le;){const Ne=Z[De],Be=z[Le]=Me?kn(z[Le]):Gr(z[Le]);if(Kr(Ne,Be))h(Ne,Be,te,null,me,de,ye,ge,Me);else break;De--,Le--}if(be>De){if(be<=Le){const Ne=Le+1,Be=NeLe)for(;be<=De;)ue(Z[be],me,de,!0),be++;else{const Ne=be,Be=be,we=new Map;for(be=Be;be<=Le;be++){const Se=z[be]=Me?kn(z[be]):Gr(z[be]);Se.key!=null&&we.set(Se.key,be)}let Re,Ee=0;const re=Le-Be+1;let se=!1,Q=0;const ae=new Array(re);for(be=0;be=re){ue(Se,me,de,!0);continue}let Pe;if(Se.key!=null)Pe=we.get(Se.key);else for(Re=Be;Re<=Le;Re++)if(ae[Re-Be]===0&&Kr(Se,z[Re])){Pe=Re;break}Pe===void 0?ue(Se,me,de,!0):(ae[Pe-Be]=be+1,Pe>=Q?Q=Pe:se=!0,h(Se,z[Pe],te,null,me,de,ye,ge,Me),Ee++)}const xe=se?vm(ae):lo;for(Re=xe.length-1,be=re-1;be>=0;be--){const Se=Be+be,Pe=z[Se],He=Se+1{const{el:de,type:ye,transition:ge,children:Me,shapeFlag:be}=Z;if(be&6){ee(Z.component.subTree,z,te,le);return}if(be&128){Z.suspense.move(z,te,le);return}if(be&64){ye.move(Z,z,te,ce);return}if(ye===yr){t(de,z,te);for(let De=0;Dege.enter(de),me);else{const{leave:De,delayLeave:Le,afterLeave:Ne}=ge,Be=()=>t(de,z,te),we=()=>{De(de,()=>{Be(),Ne&&Ne()})};Le?Le(de,Be,we):we()}else t(de,z,te)},ue=(Z,z,te,le=!1,me=!1)=>{const{type:de,props:ye,ref:ge,children:Me,dynamicChildren:be,shapeFlag:Ie,patchFlag:De,dirs:Le}=Z;if(ge!=null&&Xs(ge,null,te,Z,!0),Ie&256){z.ctx.deactivate(Z);return}const Ne=Ie&1&&Le,Be=!Kn(Z);let we;if(Be&&(we=ye&&ye.onVnodeBeforeUnmount)&&vr(we,z,Z),Ie&6)G(Z.component,te,le);else{if(Ie&128){Z.suspense.unmount(te,le);return}Ne&&on(Z,null,z,"beforeUnmount"),Ie&64?Z.type.remove(Z,z,te,me,ce,le):be&&(de!==yr||De>0&&De&64)?W(be,z,te,!1,!0):(de===yr&&De&384||!me&&Ie&16)&&W(Me,z,te),le&&T(Z)}(Be&&(we=ye&&ye.onVnodeUnmounted)||Ne)&&sr(()=>{we&&vr(we,z,Z),Ne&&on(Z,null,z,"unmounted")},te)},T=Z=>{const{type:z,el:te,anchor:le,transition:me}=Z;if(z===yr){D(te,le);return}if(z===Vo){b(Z);return}const de=()=>{x(te),me&&!me.persisted&&me.afterLeave&&me.afterLeave()};if(Z.shapeFlag&1&&me&&!me.persisted){const{leave:ye,delayLeave:ge}=me,Me=()=>ye(te,de);ge?ge(Z.el,de,Me):Me()}else de()},D=(Z,z)=>{let te;for(;Z!==z;)te=n(Z),x(Z),Z=te;x(z)},G=(Z,z,te)=>{const{bum:le,scope:me,update:de,subTree:ye,um:ge}=Z;le&&fo(le),me.stop(),de&&(de.active=!1,ue(ye,Z,z,te)),ge&&sr(ge,z),sr(()=>{Z.isUnmounted=!0},z),z&&z.pendingBranch&&!z.isUnmounted&&Z.asyncDep&&!Z.asyncResolved&&Z.suspenseId===z.pendingId&&(z.deps--,z.deps===0&&z.resolve())},W=(Z,z,te,le=!1,me=!1,de=0)=>{for(let ye=de;yeZ.shapeFlag&6?$(Z.component.subTree):Z.shapeFlag&128?Z.suspense.next():n(Z.anchor||Z.el);let J=!1;const ne=(Z,z,te)=>{Z==null?z._vnode&&ue(z._vnode,null,null,!0):h(z._vnode||null,Z,z,null,null,null,te),J||(J=!0,vu(),Hs(),J=!1),z._vnode=Z},ce={p:h,um:ue,m:ee,r:T,mt:N,mc:k,pc:V,pbc:L,n:$,o:r};let ie,pe;return d&&([ie,pe]=d(ce)),{render:ne,hydrate:ie,createApp:am(ne,ie)}}function Fi({type:r,props:d},w){return w==="svg"&&r==="foreignObject"||w==="mathml"&&r==="annotation-xml"&&d&&d.encoding&&d.encoding.includes("html")?void 0:w}function Bn({effect:r,update:d},w){r.allowRecurse=d.allowRecurse=w}function Wd(r,d){return(!r||r&&!r.pendingBranch)&&d&&!d.persisted}function qd(r,d,w=!1){const t=r.children,x=d.children;if(st(t)&&st(x))for(let v=0;v>1,r[w[u]]0&&(d[t]=w[v-1]),w[v]=t)}}for(v=w.length,s=w[v-1];v-- >0;)w[v]=s,s=d[s];return w}function Xd(r){const d=r.subTree.component;if(d)return d.asyncDep&&!d.asyncResolved?d:Xd(d)}const bm=r=>r.__isTeleport,yr=Symbol.for("v-fgt"),go=Symbol.for("v-txt"),gr=Symbol.for("v-cmt"),Vo=Symbol.for("v-stc"),Ho=[];let Hr=null;function Fr(r=!1){Ho.push(Hr=r?null:[])}function Yd(){Ho.pop(),Hr=Ho[Ho.length-1]||null}let vo=1;function Pu(r){vo+=r}function $d(r){return r.dynamicChildren=vo>0?Hr||lo:null,Yd(),vo>0&&Hr&&Hr.push(r),r}function cs(r,d,w,t,x,v){return $d(Ct(r,d,w,t,x,v,!0))}function qn(r,d,w,t,x){return $d(ft(r,d,w,t,x,!0))}function bo(r){return r?r.__v_isVNode===!0:!1}function Kr(r,d){return r.type===d.type&&r.key===d.key}const Zd=({key:r})=>r??null,Ds=({ref:r,ref_key:d,ref_for:w})=>(typeof r=="number"&&(r=""+r),r!=null?Gt(r)||fr(r)||at(r)?{i:Xt,r,k:d,f:!!w}:r:null);function Ct(r,d=null,w=null,t=0,x=null,v=r===yr?0:1,s=!1,u=!1){const o={__v_isVNode:!0,__v_skip:!0,type:r,props:d,key:d&&Zd(d),ref:d&&Ds(d),scopeId:gd,slotScopeIds:null,children:w,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:v,patchFlag:t,dynamicProps:x,dynamicChildren:null,appContext:null,ctx:Xt};return u?(al(o,w),v&128&&r.normalize(o)):w&&(o.shapeFlag|=Gt(w)?8:16),vo>0&&!s&&Hr&&(o.patchFlag>0||v&6)&&o.patchFlag!==32&&Hr.push(o),o}const ft=_m;function _m(r,d=null,w=null,t=0,x=null,v=!1){if((!r||r===bd)&&(r=gr),bo(r)){const u=un(r,d,!0);return w&&al(u,w),vo>0&&!v&&Hr&&(u.shapeFlag&6?Hr[Hr.indexOf(r)]=u:Hr.push(u)),u.patchFlag|=-2,u}if(Cm(r)&&(r=r.__vccOpts),d){d=wm(d);let{class:u,style:o}=d;u&&!Gt(u)&&(d.class=Yn(u)),Ot(o)&&(ld(o)&&!st(o)&&(o=Yt({},o)),d.style=Wa(o))}const s=Gt(r)?1:wd(r)?128:bm(r)?64:Ot(r)?4:at(r)?2:0;return Ct(r,d,w,t,x,s,v,!0)}function wm(r){return r?ld(r)||Nd(r)?Yt({},r):r:null}function un(r,d,w=!1){const{props:t,ref:x,patchFlag:v,children:s}=r,u=d?Kd(t||{},d):t;return{__v_isVNode:!0,__v_skip:!0,type:r.type,props:u,key:u&&Zd(u),ref:d&&d.ref?w&&x?st(x)?x.concat(Ds(d)):[x,Ds(d)]:Ds(d):x,scopeId:r.scopeId,slotScopeIds:r.slotScopeIds,children:s,target:r.target,targetAnchor:r.targetAnchor,staticCount:r.staticCount,shapeFlag:r.shapeFlag,patchFlag:d&&r.type!==yr?v===-1?16:v|16:v,dynamicProps:r.dynamicProps,dynamicChildren:r.dynamicChildren,appContext:r.appContext,dirs:r.dirs,transition:r.transition,component:r.component,suspense:r.suspense,ssContent:r.ssContent&&un(r.ssContent),ssFallback:r.ssFallback&&un(r.ssFallback),el:r.el,anchor:r.anchor,ctx:r.ctx,ce:r.ce}}function zo(r=" ",d=0){return ft(go,null,r,d)}function xm(r,d){const w=ft(Vo,null,r);return w.staticCount=d,w}function P_(r="",d=!1){return d?(Fr(),qn(gr,null,r)):ft(gr,null,r)}function Gr(r){return r==null||typeof r=="boolean"?ft(gr):st(r)?ft(yr,null,r.slice()):typeof r=="object"?kn(r):ft(go,null,String(r))}function kn(r){return r.el===null&&r.patchFlag!==-1||r.memo?r:un(r)}function al(r,d){let w=0;const{shapeFlag:t}=r;if(d==null)d=null;else if(st(d))w=16;else if(typeof d=="object")if(t&65){const x=d.default;x&&(x._c&&(x._d=!1),al(r,x()),x._c&&(x._d=!0));return}else{w=32;const x=d._;!x&&!Nd(d)?d._ctx=Xt:x===3&&Xt&&(Xt.slots._===1?d._=1:(d._=2,r.patchFlag|=1024))}else at(d)?(d={default:d,_ctx:Xt},w=32):(d=String(d),t&64?(w=16,d=[zo(d)]):w=8);r.children=d,r.shapeFlag|=w}function Kd(...r){const d={};for(let w=0;wZt||Xt;let Ys,ya;{const r=qc(),d=(w,t)=>{let x;return(x=r[w])||(x=r[w]=[]),x.push(t),v=>{x.length>1?x.forEach(s=>s(v)):x[0](v)}};Ys=d("__VUE_INSTANCE_SETTERS__",w=>Zt=w),ya=d("__VUE_SSR_SETTERS__",w=>ds=w)}const Qn=r=>{const d=Zt;return Ys(r),r.scope.on(),()=>{r.scope.off(),Ys(d)}},ga=()=>{Zt&&Zt.scope.off(),Ys(null)};function Qd(r){return r.vnode.shapeFlag&4}let ds=!1;function Tm(r,d=!1){d&&ya(d);const{props:w,children:t}=r.vnode,x=Qd(r);lm(r,w,x,d),dm(r,t);const v=x?Mm(r,d):void 0;return d&&ya(!1),v}function Mm(r,d){const w=r.type;r.accessCache=Object.create(null),r.proxy=new Proxy(r.ctx,Jp);const{setup:t}=w;if(t){const x=r.setupContext=t.length>1?ef(r):null,v=Qn(r);Fn();const s=Ln(t,r,0,[r.props,x]);if(Nn(),v(),Ha(s)){if(s.then(ga,ga),d)return s.then(u=>{va(r,u,d)}).catch(u=>{jo(u,r,0)});r.asyncDep=s}else va(r,s,d)}else Jd(r,d)}function va(r,d,w){at(d)?r.type.__ssrInlineRender?r.ssrRender=d:r.render=d:Ot(d)&&(r.setupState=dd(d)),Jd(r,w)}let Au;function Jd(r,d,w){const t=r.type;if(!r.render){if(!d&&Au&&!t.render){const x=t.template||sl(r).template;if(x){const{isCustomElement:v,compilerOptions:s}=r.appContext.config,{delimiters:u,compilerOptions:o}=t,c=Yt(Yt({isCustomElement:v,delimiters:u},s),o);t.render=Au(x,c)}}r.render=t.render||Vr}{const x=Qn(r);Fn();try{tm(r)}finally{Nn(),x()}}}const km={get(r,d){return br(r,"get",""),r[d]}};function ef(r){const d=w=>{r.exposed=w||{}};return{attrs:new Proxy(r.attrs,km),slots:r.slots,emit:r.emit,expose:d}}function ui(r){if(r.exposed)return r.exposeProxy||(r.exposeProxy=new Proxy(dd(pp(r.exposed)),{get(d,w){if(w in d)return d[w];if(w in Go)return Go[w](r)},has(d,w){return w in d||w in Go}}))}function ba(r,d=!0){return at(r)?r.displayName||r.name:r.name||d&&r.__name}function Cm(r){return at(r)&&"__vccOpts"in r}const jt=(r,d)=>mp(r,d,ds);function tr(r,d,w){const t=arguments.length;return t===2?Ot(d)&&!st(d)?bo(d)?ft(r,null,[d]):ft(r,d):ft(r,null,d):(t>3?w=Array.prototype.slice.call(arguments,2):t===3&&bo(w)&&(w=[w]),ft(r,d,w))}const tf="3.4.25";/** +* @vue/runtime-dom v3.4.25 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/const Om="http://www.w3.org/2000/svg",Pm="http://www.w3.org/1998/Math/MathML",Cn=typeof document<"u"?document:null,Ru=Cn&&Cn.createElement("template"),Am={insert:(r,d,w)=>{d.insertBefore(r,w||null)},remove:r=>{const d=r.parentNode;d&&d.removeChild(r)},createElement:(r,d,w,t)=>{const x=d==="svg"?Cn.createElementNS(Om,r):d==="mathml"?Cn.createElementNS(Pm,r):Cn.createElement(r,w?{is:w}:void 0);return r==="select"&&t&&t.multiple!=null&&x.setAttribute("multiple",t.multiple),x},createText:r=>Cn.createTextNode(r),createComment:r=>Cn.createComment(r),setText:(r,d)=>{r.nodeValue=d},setElementText:(r,d)=>{r.textContent=d},parentNode:r=>r.parentNode,nextSibling:r=>r.nextSibling,querySelector:r=>Cn.querySelector(r),setScopeId(r,d){r.setAttribute(d,"")},insertStaticContent(r,d,w,t,x,v){const s=w?w.previousSibling:d.lastChild;if(x&&(x===v||x.nextSibling))for(;d.insertBefore(x.cloneNode(!0),w),!(x===v||!(x=x.nextSibling)););else{Ru.innerHTML=t==="svg"?`${r}`:t==="mathml"?`${r}`:r;const u=Ru.content;if(t==="svg"||t==="mathml"){const o=u.firstChild;for(;o.firstChild;)u.appendChild(o.firstChild);u.removeChild(o)}d.insertBefore(u,w)}return[s?s.nextSibling:d.firstChild,w?w.previousSibling:d.lastChild]}},jn="transition",Io="animation",es=Symbol("_vtc"),fs=(r,{slots:d})=>tr(zp,Rm(r),d);fs.displayName="Transition";const rf={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String};fs.props=Yt({},Sd,rf);const Gn=(r,d=[])=>{st(r)?r.forEach(w=>w(...d)):r&&r(...d)},Lu=r=>r?st(r)?r.some(d=>d.length>1):r.length>1:!1;function Rm(r){const d={};for(const I in r)I in rf||(d[I]=r[I]);if(r.css===!1)return d;const{name:w="v",type:t,duration:x,enterFromClass:v=`${w}-enter-from`,enterActiveClass:s=`${w}-enter-active`,enterToClass:u=`${w}-enter-to`,appearFromClass:o=v,appearActiveClass:c=s,appearToClass:g=u,leaveFromClass:p=`${w}-leave-from`,leaveActiveClass:n=`${w}-leave-active`,leaveToClass:i=`${w}-leave-to`}=r,a=Lm(x),h=a&&a[0],y=a&&a[1],{onBeforeEnter:l,onEnter:f,onEnterCancelled:m,onLeave:b,onLeaveCancelled:j,onBeforeAppear:M=l,onAppear:E=f,onAppearCancelled:k=m}=d,P=(I,A,N)=>{Vn(I,A?g:u),Vn(I,A?c:s),N&&N()},L=(I,A)=>{I._isLeaving=!1,Vn(I,p),Vn(I,i),Vn(I,n),A&&A()},C=I=>(A,N)=>{const F=I?E:f,B=()=>P(A,I,N);Gn(F,[A,B]),Iu(()=>{Vn(A,I?o:v),Sn(A,I?g:u),Lu(F)||Du(A,t,h,B)})};return Yt(d,{onBeforeEnter(I){Gn(l,[I]),Sn(I,v),Sn(I,s)},onBeforeAppear(I){Gn(M,[I]),Sn(I,o),Sn(I,c)},onEnter:C(!1),onAppear:C(!0),onLeave(I,A){I._isLeaving=!0;const N=()=>L(I,A);Sn(I,p),Sn(I,n),Fm(),Iu(()=>{I._isLeaving&&(Vn(I,p),Sn(I,i),Lu(b)||Du(I,t,y,N))}),Gn(b,[I,N])},onEnterCancelled(I){P(I,!1),Gn(m,[I])},onAppearCancelled(I){P(I,!0),Gn(k,[I])},onLeaveCancelled(I){L(I),Gn(j,[I])}})}function Lm(r){if(r==null)return null;if(Ot(r))return[Ni(r.enter),Ni(r.leave)];{const d=Ni(r);return[d,d]}}function Ni(r){return Wc(r)}function Sn(r,d){d.split(/\s+/).forEach(w=>w&&r.classList.add(w)),(r[es]||(r[es]=new Set)).add(d)}function Vn(r,d){d.split(/\s+/).forEach(t=>t&&r.classList.remove(t));const w=r[es];w&&(w.delete(d),w.size||(r[es]=void 0))}function Iu(r){requestAnimationFrame(()=>{requestAnimationFrame(r)})}let Im=0;function Du(r,d,w,t){const x=r._endId=++Im,v=()=>{x===r._endId&&t()};if(w)return setTimeout(v,w);const{type:s,timeout:u,propCount:o}=Dm(r,d);if(!s)return t();const c=s+"end";let g=0;const p=()=>{r.removeEventListener(c,n),v()},n=i=>{i.target===r&&++g>=o&&p()};setTimeout(()=>{g(w[a]||"").split(", "),x=t(`${jn}Delay`),v=t(`${jn}Duration`),s=Fu(x,v),u=t(`${Io}Delay`),o=t(`${Io}Duration`),c=Fu(u,o);let g=null,p=0,n=0;d===jn?s>0&&(g=jn,p=s,n=v.length):d===Io?c>0&&(g=Io,p=c,n=o.length):(p=Math.max(s,c),g=p>0?s>c?jn:Io:null,n=g?g===jn?v.length:o.length:0);const i=g===jn&&/\b(transform|all)(,|$)/.test(t(`${jn}Property`).toString());return{type:g,timeout:p,propCount:n,hasTransform:i}}function Fu(r,d){for(;r.lengthNu(w)+Nu(r[t])))}function Nu(r){return r==="auto"?0:Number(r.slice(0,-1).replace(",","."))*1e3}function Fm(){return document.body.offsetHeight}function Nm(r,d,w){const t=r[es];t&&(d=(d?[d,...t]:[...t]).join(" ")),d==null?r.removeAttribute("class"):w?r.setAttribute("class",d):r.className=d}const Uu=Symbol("_vod"),Um=Symbol("_vsh"),Bm=Symbol(""),Gm=/(^|;)\s*display\s*:/;function Vm(r,d,w){const t=r.style,x=Gt(w);let v=!1;if(w&&!x){if(d)if(Gt(d))for(const s of d.split(";")){const u=s.slice(0,s.indexOf(":")).trim();w[u]==null&&Fs(t,u,"")}else for(const s in d)w[s]==null&&Fs(t,s,"");for(const s in w)s==="display"&&(v=!0),Fs(t,s,w[s])}else if(x){if(d!==w){const s=t[Bm];s&&(w+=";"+s),t.cssText=w,v=Gm.test(w)}}else d&&r.removeAttribute("style");Uu in r&&(r[Uu]=v?t.display:"",r[Um]&&(t.display="none"))}const Bu=/\s*!important$/;function Fs(r,d,w){if(st(w))w.forEach(t=>Fs(r,d,t));else if(w==null&&(w=""),d.startsWith("--"))r.setProperty(d,w);else{const t=Hm(r,d);Bu.test(w)?r.setProperty(xo(t),w.replace(Bu,""),"important"):r[t]=w}}const Gu=["Webkit","Moz","ms"],Ui={};function Hm(r,d){const w=Ui[d];if(w)return w;let t=an(d);if(t!=="filter"&&t in r)return Ui[d]=t;t=oi(t);for(let x=0;xBi||($m.then(()=>Bi=0),Bi=Date.now());function Km(r,d){const w=t=>{if(!t._vts)t._vts=Date.now();else if(t._vts<=w.attached)return;zr(Qm(t,w.value),d,5,[t])};return w.value=r,w.attached=Zm(),w}function Qm(r,d){if(st(d)){const w=r.stopImmediatePropagation;return r.stopImmediatePropagation=()=>{w.call(r),r._stopped=!0},d.map(t=>x=>!x._stopped&&t&&t(x))}else return d}const Wu=r=>r.charCodeAt(0)===111&&r.charCodeAt(1)===110&&r.charCodeAt(2)>96&&r.charCodeAt(2)<123,Jm=(r,d,w,t,x,v,s,u,o)=>{const c=x==="svg";d==="class"?Nm(r,t,c):d==="style"?Vm(r,w,t):os(d)?Ga(d)||Xm(r,d,w,t,s):(d[0]==="."?(d=d.slice(1),!0):d[0]==="^"?(d=d.slice(1),!1):ey(r,d,t,c))?Wm(r,d,t,v,s,u,o):(d==="true-value"?r._trueValue=t:d==="false-value"&&(r._falseValue=t),zm(r,d,t,c))};function ey(r,d,w,t){if(t)return!!(d==="innerHTML"||d==="textContent"||d in r&&Wu(d)&&at(w));if(d==="spellcheck"||d==="draggable"||d==="translate"||d==="form"||d==="list"&&r.tagName==="INPUT"||d==="type"&&r.tagName==="TEXTAREA")return!1;if(d==="width"||d==="height"){const x=r.tagName;if(x==="IMG"||x==="VIDEO"||x==="CANVAS"||x==="SOURCE")return!1}return Wu(d)&&Gt(w)?!1:d in r}const qu=r=>{const d=r.props["onUpdate:modelValue"]||!1;return st(d)?w=>fo(d,w):d};function ty(r){r.target.composing=!0}function Xu(r){const d=r.target;d.composing&&(d.composing=!1,d.dispatchEvent(new Event("input")))}const Gi=Symbol("_assign"),A_={created(r,{modifiers:{lazy:d,trim:w,number:t}},x){r[Gi]=qu(x);const v=t||x.props&&x.props.type==="number";so(r,d?"change":"input",s=>{if(s.target.composing)return;let u=r.value;w&&(u=u.trim()),v&&(u=oa(u)),r[Gi](u)}),w&&so(r,"change",()=>{r.value=r.value.trim()}),d||(so(r,"compositionstart",ty),so(r,"compositionend",Xu),so(r,"change",Xu))},mounted(r,{value:d}){r.value=d??""},beforeUpdate(r,{value:d,modifiers:{lazy:w,trim:t,number:x}},v){if(r[Gi]=qu(v),r.composing)return;const s=(x||r.type==="number")&&!/^0\d/.test(r.value)?oa(r.value):r.value,u=d??"";s!==u&&(document.activeElement===r&&r.type!=="range"&&(w||t&&r.value.trim()===u)||(r.value=u))}},nf=Yt({patchProp:Jm},Am);let Wo,Yu=!1;function ry(){return Wo||(Wo=ym(nf))}function ny(){return Wo=Yu?Wo:gm(nf),Yu=!0,Wo}const oy=(...r)=>{const d=ry().createApp(...r),{mount:w}=d;return d.mount=t=>{const x=sf(t);if(!x)return;const v=d._component;!at(v)&&!v.render&&!v.template&&(v.template=x.innerHTML),x.innerHTML="";const s=w(x,!1,of(x));return x instanceof Element&&(x.removeAttribute("v-cloak"),x.setAttribute("data-v-app","")),s},d},sy=(...r)=>{const d=ny().createApp(...r),{mount:w}=d;return d.mount=t=>{const x=sf(t);if(x)return w(x,!0,of(x))},d};function of(r){if(r instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&r instanceof MathMLElement)return"mathml"}function sf(r){return Gt(r)?document.querySelector(r):r}const iy=/"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/,ay=/"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/,ly=/^\s*["[{]|^\s*-?\d{1,16}(\.\d{1,17})?([Ee][+-]?\d+)?\s*$/;function uy(r,d){if(r==="__proto__"||r==="constructor"&&d&&typeof d=="object"&&"prototype"in d){cy(r);return}return d}function cy(r){console.warn(`[destr] Dropping "${r}" key to prevent prototype pollution.`)}function $s(r,d={}){if(typeof r!="string")return r;const w=r.trim();if(r[0]==='"'&&r.endsWith('"')&&!r.includes("\\"))return w.slice(1,-1);if(w.length<=9){const t=w.toLowerCase();if(t==="true")return!0;if(t==="false")return!1;if(t==="undefined")return;if(t==="null")return null;if(t==="nan")return Number.NaN;if(t==="infinity")return Number.POSITIVE_INFINITY;if(t==="-infinity")return Number.NEGATIVE_INFINITY}if(!ly.test(r)){if(d.strict)throw new SyntaxError("[destr] Invalid JSON");return r}try{if(iy.test(r)||ay.test(r)){if(d.strict)throw new Error("[destr] Possible prototype pollution");return JSON.parse(r,uy)}return JSON.parse(r)}catch(t){if(d.strict)throw t;return r}}const dy=/#/g,fy=/&/g,hy=/\//g,py=/=/g,ll=/\+/g,my=/%5e/gi,yy=/%60/gi,gy=/%7c/gi,vy=/%20/gi;function by(r){return encodeURI(""+r).replace(gy,"|")}function _a(r){return by(typeof r=="string"?r:JSON.stringify(r)).replace(ll,"%2B").replace(vy,"+").replace(dy,"%23").replace(fy,"%26").replace(yy,"`").replace(my,"^").replace(hy,"%2F")}function Vi(r){return _a(r).replace(py,"%3D")}function Zs(r=""){try{return decodeURIComponent(""+r)}catch{return""+r}}function _y(r){return Zs(r.replace(ll," "))}function wy(r){return Zs(r.replace(ll," "))}function af(r=""){const d={};r[0]==="?"&&(r=r.slice(1));for(const w of r.split("&")){const t=w.match(/([^=]+)=?(.*)/)||[];if(t.length<2)continue;const x=_y(t[1]);if(x==="__proto__"||x==="constructor")continue;const v=wy(t[2]||"");d[x]===void 0?d[x]=v:Array.isArray(d[x])?d[x].push(v):d[x]=[d[x],v]}return d}function xy(r,d){return(typeof d=="number"||typeof d=="boolean")&&(d=String(d)),d?Array.isArray(d)?d.map(w=>`${Vi(r)}=${_a(w)}`).join("&"):`${Vi(r)}=${_a(d)}`:Vi(r)}function jy(r){return Object.keys(r).filter(d=>r[d]!==void 0).map(d=>xy(d,r[d])).filter(Boolean).join("&")}const Sy=/^[\s\w\0+.-]{2,}:([/\\]{1,2})/,Ey=/^[\s\w\0+.-]{2,}:([/\\]{2})?/,Ty=/^([/\\]\s*){2,}[^/\\]/,My=/^[\s\0]*(blob|data|javascript|vbscript):$/i,ky=/\/$|\/\?|\/#/,Cy=/^\.?\//;function yn(r,d={}){return typeof d=="boolean"&&(d={acceptRelative:d}),d.strict?Sy.test(r):Ey.test(r)||(d.acceptRelative?Ty.test(r):!1)}function Oy(r){return!!r&&My.test(r)}function wa(r="",d){return d?ky.test(r):r.endsWith("/")}function ci(r="",d){if(!d)return(wa(r)?r.slice(0,-1):r)||"/";if(!wa(r,!0))return r||"/";let w=r,t="";const x=r.indexOf("#");x>=0&&(w=r.slice(0,x),t=r.slice(x));const[v,...s]=w.split("?");return((v.endsWith("/")?v.slice(0,-1):v)||"/")+(s.length>0?`?${s.join("?")}`:"")+t}function Ks(r="",d){if(!d)return r.endsWith("/")?r:r+"/";if(wa(r,!0))return r||"/";let w=r,t="";const x=r.indexOf("#");if(x>=0&&(w=r.slice(0,x),t=r.slice(x),!w))return t;const[v,...s]=w.split("?");return v+"/"+(s.length>0?`?${s.join("?")}`:"")+t}function Py(r=""){return r.startsWith("/")}function $u(r=""){return Py(r)?r:"/"+r}function Ay(r,d){if(uf(d)||yn(r))return r;const w=ci(d);return r.startsWith(w)?r:di(w,r)}function Zu(r,d){if(uf(d))return r;const w=ci(d);if(!r.startsWith(w))return r;const t=r.slice(w.length);return t[0]==="/"?t:"/"+t}function lf(r,d){const w=hs(r),t={...af(w.search),...d};return w.search=jy(t),Iy(w)}function uf(r){return!r||r==="/"}function Ry(r){return r&&r!=="/"}function di(r,...d){let w=r||"";for(const t of d.filter(x=>Ry(x)))if(w){const x=t.replace(Cy,"");w=Ks(w)+x}else w=t;return w}function cf(...r){var s,u,o,c;const d=/\/(?!\/)/,w=r.filter(Boolean),t=[];let x=0;for(const g of w)if(!(!g||g==="/")){for(const[p,n]of g.split(d).entries())if(!(!n||n===".")){if(n===".."){if(t.length===1&&yn(t[0]))continue;t.pop(),x--;continue}if(p===1&&((s=t[t.length-1])!=null&&s.endsWith(":/"))){t[t.length-1]+="/"+n;continue}t.push(n),x++}}let v=t.join("/");return x>=0?(u=w[0])!=null&&u.startsWith("/")&&!v.startsWith("/")?v="/"+v:(o=w[0])!=null&&o.startsWith("./")&&!v.startsWith("./")&&(v="./"+v):v="../".repeat(-1*x)+v,(c=w[w.length-1])!=null&&c.endsWith("/")&&!v.endsWith("/")&&(v+="/"),v}function Ly(r,d,w={}){return w.trailingSlash||(r=Ks(r),d=Ks(d)),w.leadingSlash||(r=$u(r),d=$u(d)),w.encoding||(r=Zs(r),d=Zs(d)),r===d}const df=Symbol.for("ufo:protocolRelative");function hs(r="",d){const w=r.match(/^[\s\0]*(blob:|data:|javascript:|vbscript:)(.*)/i);if(w){const[,p,n=""]=w;return{protocol:p.toLowerCase(),pathname:n,href:p+n,auth:"",host:"",search:"",hash:""}}if(!yn(r,{acceptRelative:!0}))return d?hs(d+r):Ku(r);const[,t="",x,v=""]=r.replace(/\\/g,"/").match(/^[\s\0]*([\w+.-]{2,}:)?\/\/([^/@]+@)?(.*)/)||[],[,s="",u=""]=v.match(/([^#/?]*)(.*)?/)||[],{pathname:o,search:c,hash:g}=Ku(u.replace(/\/(?=[A-Za-z]:)/,""));return{protocol:t.toLowerCase(),auth:x?x.slice(0,Math.max(0,x.length-1)):"",host:s,pathname:o,search:c,hash:g,[df]:!t}}function Ku(r=""){const[d="",w="",t=""]=(r.match(/([^#?]*)(\?[^#]*)?(#.*)?/)||[]).splice(1);return{pathname:d,search:w,hash:t}}function Iy(r){const d=r.pathname||"",w=r.search?(r.search.startsWith("?")?"":"?")+r.search:"",t=r.hash||"",x=r.auth?r.auth+"@":"",v=r.host||"";return(r.protocol||r[df]?(r.protocol||"")+"//":"")+x+v+d+w+t}class Dy extends Error{constructor(d,w){super(d,w),this.name="FetchError",w!=null&&w.cause&&!this.cause&&(this.cause=w.cause)}}function Fy(r){var o,c,g,p,n;const d=((o=r.error)==null?void 0:o.message)||((c=r.error)==null?void 0:c.toString())||"",w=((g=r.request)==null?void 0:g.method)||((p=r.options)==null?void 0:p.method)||"GET",t=((n=r.request)==null?void 0:n.url)||String(r.request)||"/",x=`[${w}] ${JSON.stringify(t)}`,v=r.response?`${r.response.status} ${r.response.statusText}`:"",s=`${x}: ${v}${d?` ${d}`:""}`,u=new Dy(s,r.error?{cause:r.error}:void 0);for(const i of["request","options","response"])Object.defineProperty(u,i,{get(){return r[i]}});for(const[i,a]of[["data","_data"],["status","status"],["statusCode","status"],["statusText","statusText"],["statusMessage","statusText"]])Object.defineProperty(u,i,{get(){return r.response&&r.response[a]}});return u}const Ny=new Set(Object.freeze(["PATCH","POST","PUT","DELETE"]));function Qu(r="GET"){return Ny.has(r.toUpperCase())}function Uy(r){if(r===void 0)return!1;const d=typeof r;return d==="string"||d==="number"||d==="boolean"||d===null?!0:d!=="object"?!1:Array.isArray(r)?!0:r.buffer?!1:r.constructor&&r.constructor.name==="Object"||typeof r.toJSON=="function"}const By=new Set(["image/svg","application/xml","application/xhtml","application/html"]),Gy=/^application\/(?:[\w!#$%&*.^`~-]*\+)?json(;.+)?$/i;function Vy(r=""){if(!r)return"json";const d=r.split(";").shift()||"";return Gy.test(d)?"json":By.has(d)||d.startsWith("text/")?"text":"blob"}function Hy(r,d,w=globalThis.Headers){const t={...d,...r};if(d!=null&&d.params&&(r!=null&&r.params)&&(t.params={...d==null?void 0:d.params,...r==null?void 0:r.params}),d!=null&&d.query&&(r!=null&&r.query)&&(t.query={...d==null?void 0:d.query,...r==null?void 0:r.query}),d!=null&&d.headers&&(r!=null&&r.headers)){t.headers=new w((d==null?void 0:d.headers)||{});for(const[x,v]of new w((r==null?void 0:r.headers)||{}))t.headers.set(x,v)}return t}const zy=new Set([408,409,425,429,500,502,503,504]),Wy=new Set([101,204,205,304]);function ff(r={}){const{fetch:d=globalThis.fetch,Headers:w=globalThis.Headers,AbortController:t=globalThis.AbortController}=r;async function x(u){const o=u.error&&u.error.name==="AbortError"&&!u.options.timeout||!1;if(u.options.retry!==!1&&!o){let g;typeof u.options.retry=="number"?g=u.options.retry:g=Qu(u.options.method)?0:1;const p=u.response&&u.response.status||500;if(g>0&&(Array.isArray(u.options.retryStatusCodes)?u.options.retryStatusCodes.includes(p):zy.has(p))){const n=u.options.retryDelay||0;return n>0&&await new Promise(i=>setTimeout(i,n)),v(u.request,{...u.options,retry:g-1})}}const c=Fy(u);throw Error.captureStackTrace&&Error.captureStackTrace(c,v),c}const v=async function(o,c={}){var i;const g={request:o,options:Hy(c,r.defaults,w),response:void 0,error:void 0};g.options.method=(i=g.options.method)==null?void 0:i.toUpperCase(),g.options.onRequest&&await g.options.onRequest(g),typeof g.request=="string"&&(g.options.baseURL&&(g.request=Ay(g.request,g.options.baseURL)),(g.options.query||g.options.params)&&(g.request=lf(g.request,{...g.options.params,...g.options.query}))),g.options.body&&Qu(g.options.method)&&(Uy(g.options.body)?(g.options.body=typeof g.options.body=="string"?g.options.body:JSON.stringify(g.options.body),g.options.headers=new w(g.options.headers||{}),g.options.headers.has("content-type")||g.options.headers.set("content-type","application/json"),g.options.headers.has("accept")||g.options.headers.set("accept","application/json")):("pipeTo"in g.options.body&&typeof g.options.body.pipeTo=="function"||typeof g.options.body.pipe=="function")&&("duplex"in g.options||(g.options.duplex="half")));let p;if(!g.options.signal&&g.options.timeout){const a=new t;p=setTimeout(()=>a.abort(),g.options.timeout),g.options.signal=a.signal}try{g.response=await d(g.request,g.options)}catch(a){return g.error=a,g.options.onRequestError&&await g.options.onRequestError(g),await x(g)}finally{p&&clearTimeout(p)}if(g.response.body&&!Wy.has(g.response.status)&&g.options.method!=="HEAD"){const a=(g.options.parseResponse?"json":g.options.responseType)||Vy(g.response.headers.get("content-type")||"");switch(a){case"json":{const h=await g.response.text(),y=g.options.parseResponse||$s;g.response._data=y(h);break}case"stream":{g.response._data=g.response.body;break}default:g.response._data=await g.response[a]()}}return g.options.onResponse&&await g.options.onResponse(g),!g.options.ignoreResponseError&&g.response.status>=400&&g.response.status<600?(g.options.onResponseError&&await g.options.onResponseError(g),await x(g)):g.response},s=async function(o,c){return(await v(o,c))._data};return s.raw=v,s.native=(...u)=>d(...u),s.create=(u={})=>ff({...r,defaults:{...r.defaults,...u}}),s}const ul=function(){if(typeof globalThis<"u")return globalThis;if(typeof self<"u")return self;if(typeof window<"u")return window;if(typeof global<"u")return global;throw new Error("unable to locate global object")}(),qy=ul.fetch||(()=>Promise.reject(new Error("[ofetch] global.fetch is not supported!"))),Xy=ul.Headers,Yy=ul.AbortController,$y=ff({fetch:qy,Headers:Xy,AbortController:Yy}),Zy=$y,Ky=()=>{var r;return((r=window==null?void 0:window.__NUXT__)==null?void 0:r.config)||{}},Qs=Ky().app,Qy=()=>Qs.baseURL,Jy=()=>Qs.buildAssetsDir,cl=(...r)=>cf(hf(),Jy(),...r),hf=(...r)=>{const d=Qs.cdnURL||Qs.baseURL;return r.length?cf(d,...r):d};globalThis.__buildAssetsURL=cl,globalThis.__publicAssetsURL=hf;globalThis.$fetch||(globalThis.$fetch=Zy.create({baseURL:Qy()}));function xa(r,d={},w){for(const t in r){const x=r[t],v=w?`${w}:${t}`:t;typeof x=="object"&&x!==null?xa(x,d,v):typeof x=="function"&&(d[v]=x)}return d}const eg={run:r=>r()},tg=()=>eg,pf=typeof console.createTask<"u"?console.createTask:tg;function rg(r,d){const w=d.shift(),t=pf(w);return r.reduce((x,v)=>x.then(()=>t.run(()=>v(...d))),Promise.resolve())}function ng(r,d){const w=d.shift(),t=pf(w);return Promise.all(r.map(x=>t.run(()=>x(...d))))}function Hi(r,d){for(const w of[...r])w(d)}class og{constructor(){this._hooks={},this._before=void 0,this._after=void 0,this._deprecatedMessages=void 0,this._deprecatedHooks={},this.hook=this.hook.bind(this),this.callHook=this.callHook.bind(this),this.callHookWith=this.callHookWith.bind(this)}hook(d,w,t={}){if(!d||typeof w!="function")return()=>{};const x=d;let v;for(;this._deprecatedHooks[d];)v=this._deprecatedHooks[d],d=v.to;if(v&&!t.allowDeprecated){let s=v.message;s||(s=`${x} hook has been deprecated`+(v.to?`, please use ${v.to}`:"")),this._deprecatedMessages||(this._deprecatedMessages=new Set),this._deprecatedMessages.has(s)||(console.warn(s),this._deprecatedMessages.add(s))}if(!w.name)try{Object.defineProperty(w,"name",{get:()=>"_"+d.replace(/\W+/g,"_")+"_hook_cb",configurable:!0})}catch{}return this._hooks[d]=this._hooks[d]||[],this._hooks[d].push(w),()=>{w&&(this.removeHook(d,w),w=void 0)}}hookOnce(d,w){let t,x=(...v)=>(typeof t=="function"&&t(),t=void 0,x=void 0,w(...v));return t=this.hook(d,x),t}removeHook(d,w){if(this._hooks[d]){const t=this._hooks[d].indexOf(w);t!==-1&&this._hooks[d].splice(t,1),this._hooks[d].length===0&&delete this._hooks[d]}}deprecateHook(d,w){this._deprecatedHooks[d]=typeof w=="string"?{to:w}:w;const t=this._hooks[d]||[];delete this._hooks[d];for(const x of t)this.hook(d,x)}deprecateHooks(d){Object.assign(this._deprecatedHooks,d);for(const w in d)this.deprecateHook(w,d[w])}addHooks(d){const w=xa(d),t=Object.keys(w).map(x=>this.hook(x,w[x]));return()=>{for(const x of t.splice(0,t.length))x()}}removeHooks(d){const w=xa(d);for(const t in w)this.removeHook(t,w[t])}removeAllHooks(){for(const d in this._hooks)delete this._hooks[d]}callHook(d,...w){return w.unshift(d),this.callHookWith(rg,d,...w)}callHookParallel(d,...w){return w.unshift(d),this.callHookWith(ng,d,...w)}callHookWith(d,w,...t){const x=this._before||this._after?{name:w,args:t,context:{}}:void 0;this._before&&Hi(this._before,x);const v=d(w in this._hooks?[...this._hooks[w]]:[],t);return v instanceof Promise?v.finally(()=>{this._after&&x&&Hi(this._after,x)}):(this._after&&x&&Hi(this._after,x),v)}beforeEach(d){return this._before=this._before||[],this._before.push(d),()=>{if(this._before!==void 0){const w=this._before.indexOf(d);w!==-1&&this._before.splice(w,1)}}}afterEach(d){return this._after=this._after||[],this._after.push(d),()=>{if(this._after!==void 0){const w=this._after.indexOf(d);w!==-1&&this._after.splice(w,1)}}}}function mf(){return new og}function sg(r={}){let d,w=!1;const t=s=>{if(d&&d!==s)throw new Error("Context conflict")};let x;if(r.asyncContext){const s=r.AsyncLocalStorage||globalThis.AsyncLocalStorage;s?x=new s:console.warn("[unctx] `AsyncLocalStorage` is not provided.")}const v=()=>{if(x&&d===void 0){const s=x.getStore();if(s!==void 0)return s}return d};return{use:()=>{const s=v();if(s===void 0)throw new Error("Context is not available");return s},tryUse:()=>v(),set:(s,u)=>{u||t(s),d=s,w=!0},unset:()=>{d=void 0,w=!1},call:(s,u)=>{t(s),d=s;try{return x?x.run(s,u):u()}finally{w||(d=void 0)}},async callAsync(s,u){d=s;const o=()=>{d=s},c=()=>d===s?o:void 0;ja.add(c);try{const g=x?x.run(s,u):u();return w||(d=void 0),await g}finally{ja.delete(c)}}}}function ig(r={}){const d={};return{get(w,t={}){return d[w]||(d[w]=sg({...r,...t})),d[w],d[w]}}}const Js=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof global<"u"?global:typeof window<"u"?window:{},Ju="__unctx__",ag=Js[Ju]||(Js[Ju]=ig()),lg=(r,d={})=>ag.get(r,d),ec="__unctx_async_handlers__",ja=Js[ec]||(Js[ec]=new Set);function ts(r){const d=[];for(const x of ja){const v=x();v&&d.push(v)}const w=()=>{for(const x of d)x()};let t=r();return t&&typeof t=="object"&&"catch"in t&&(t=t.catch(x=>{throw w(),x})),[t,w]}const yf=lg("nuxt-app",{asyncContext:!1}),ug="__nuxt_plugin";function cg(r){let d=0;const w={_scope:Wh(),provide:void 0,globalName:"nuxt",versions:{get nuxt(){return"3.11.2"},get vue(){return w.vueApp.version}},payload:Un({data:{},state:{},once:new Set,_errors:{},...window.__NUXT__??{}}),static:{data:{}},runWithContext:x=>w._scope.run(()=>hg(w,x)),isHydrating:!0,deferHydration(){if(!w.isHydrating)return()=>{};d++;let x=!1;return()=>{if(!x&&(x=!0,d--,d===0))return w.isHydrating=!1,w.callHook("app:suspense:resolve")}},_asyncDataPromises:{},_asyncData:{},_payloadRevivers:{},...r};w.hooks=mf(),w.hook=w.hooks.hook,w.callHook=w.hooks.callHook,w.provide=(x,v)=>{const s="$"+x;Os(w,s,v),Os(w.vueApp.config.globalProperties,s,v)},Os(w.vueApp,"$nuxt",w),Os(w.vueApp.config.globalProperties,"$nuxt",w);{window.addEventListener("nuxt.preloadError",v=>{w.callHook("app:chunkError",{error:v.payload})}),window.useNuxtApp=window.useNuxtApp||It;const x=w.hook("app:error",(...v)=>{console.error("[nuxt] error caught during app initialization",...v)});w.hook("app:mounted",x)}const t=w.payload.config;return w.provide("config",t),w}async function dg(r,d){if(d.hooks&&r.hooks.addHooks(d.hooks),typeof d=="function"){const{provide:w}=await r.runWithContext(()=>d(r))||{};if(w&&typeof w=="object")for(const t in w)r.provide(t,w[t])}}async function fg(r,d){const w=[],t=[],x=[],v=[];let s=0;async function u(o){var g;const c=((g=o.dependsOn)==null?void 0:g.filter(p=>d.some(n=>n._name===p)&&!w.includes(p)))??[];if(c.length>0)t.push([new Set(c),o]);else{const p=dg(r,o).then(async()=>{o._name&&(w.push(o._name),await Promise.all(t.map(async([n,i])=>{n.has(o._name)&&(n.delete(o._name),n.size===0&&(s++,await u(i)))})))});o.parallel?x.push(p.catch(n=>v.push(n))):await p}}for(const o of d)await u(o);if(await Promise.all(x),s)for(let o=0;o{}),r,{[ug]:!0,_name:d})}function hg(r,d,w){const t=()=>d();return yf.set(r),r.vueApp.runWithContext(t)}function pg(){var d;let r;return Id()&&(r=(d=So())==null?void 0:d.appContext.app.$nuxt),r=r||yf.tryUse(),r||null}function It(){const r=pg();if(!r)throw new Error("[nuxt] instance unavailable");return r}function fi(r){return It().$config}function Os(r,d,w){Object.defineProperty(r,d,{get:()=>w})}function mg(r,d){return{ctx:{table:r},matchAll:w=>vf(w,r)}}function gf(r){const d={};for(const w in r)d[w]=w==="dynamic"?new Map(Object.entries(r[w]).map(([t,x])=>[t,gf(x)])):new Map(Object.entries(r[w]));return d}function yg(r){return mg(gf(r))}function vf(r,d,w){r.endsWith("/")&&(r=r.slice(0,-1)||"/");const t=[];for(const[v,s]of tc(d.wildcard))(r===v||r.startsWith(v+"/"))&&t.push(s);for(const[v,s]of tc(d.dynamic))if(r.startsWith(v+"/")){const u="/"+r.slice(v.length).split("/").splice(2).join("/");t.push(...vf(u,s))}const x=d.static.get(r);return x&&t.push(x),t.filter(Boolean)}function tc(r){return[...r.entries()].sort((d,w)=>d[0].length-w[0].length)}function zi(r){if(r===null||typeof r!="object")return!1;const d=Object.getPrototypeOf(r);return d!==null&&d!==Object.prototype&&Object.getPrototypeOf(d)!==null||Symbol.iterator in r?!1:Symbol.toStringTag in r?Object.prototype.toString.call(r)==="[object Module]":!0}function Sa(r,d,w=".",t){if(!zi(d))return Sa(r,{},w,t);const x=Object.assign({},d);for(const v in r){if(v==="__proto__"||v==="constructor")continue;const s=r[v];s!=null&&(t&&t(x,v,s,w)||(Array.isArray(s)&&Array.isArray(x[v])?x[v]=[...s,...x[v]]:zi(s)&&zi(x[v])?x[v]=Sa(s,x[v],(w?`${w}.`:"")+v.toString(),t):x[v]=s))}return x}function bf(r){return(...d)=>d.reduce((w,t)=>Sa(w,t,"",r),{})}const _f=bf(),gg=bf((r,d,w)=>{if(r[d]!==void 0&&typeof w=="function")return r[d]=w(r[d]),!0});function vg(r,d){try{return d in r}catch{return!1}}var bg=Object.defineProperty,_g=(r,d,w)=>d in r?bg(r,d,{enumerable:!0,configurable:!0,writable:!0,value:w}):r[d]=w,zn=(r,d,w)=>(_g(r,typeof d!="symbol"?d+"":d,w),w);class Ea extends Error{constructor(d,w={}){super(d,w),zn(this,"statusCode",500),zn(this,"fatal",!1),zn(this,"unhandled",!1),zn(this,"statusMessage"),zn(this,"data"),zn(this,"cause"),w.cause&&!this.cause&&(this.cause=w.cause)}toJSON(){const d={message:this.message,statusCode:Ma(this.statusCode,500)};return this.statusMessage&&(d.statusMessage=wf(this.statusMessage)),this.data!==void 0&&(d.data=this.data),d}}zn(Ea,"__h3_error__",!0);function Ta(r){if(typeof r=="string")return new Ea(r);if(wg(r))return r;const d=new Ea(r.message??r.statusMessage??"",{cause:r.cause||r});if(vg(r,"stack"))try{Object.defineProperty(d,"stack",{get(){return r.stack}})}catch{try{d.stack=r.stack}catch{}}if(r.data&&(d.data=r.data),r.statusCode?d.statusCode=Ma(r.statusCode,d.statusCode):r.status&&(d.statusCode=Ma(r.status,d.statusCode)),r.statusMessage?d.statusMessage=r.statusMessage:r.statusText&&(d.statusMessage=r.statusText),d.statusMessage){const w=d.statusMessage;wf(d.statusMessage)!==w&&console.warn("[h3] Please prefer using `message` for longer error messages instead of `statusMessage`. In the future, `statusMessage` will be sanitized by default.")}return r.fatal!==void 0&&(d.fatal=r.fatal),r.unhandled!==void 0&&(d.unhandled=r.unhandled),d}function wg(r){var d;return((d=r==null?void 0:r.constructor)==null?void 0:d.__h3_error__)===!0}const xg=/[^\u0009\u0020-\u007E]/g;function wf(r=""){return r.replace(xg,"")}function Ma(r,d=200){return!r||(typeof r=="string"&&(r=Number.parseInt(r,10)),r<100||r>999)?d:r}const xf=Symbol("layout-meta"),ps=Symbol("route"),qr=()=>{var r;return(r=It())==null?void 0:r.$router},hi=()=>Id()?Ht(ps,It()._route):It()._route;const jg=()=>{try{if(It()._processingMiddleware)return!0}catch{return!1}return!1},Sg=(r,d)=>{r||(r="/");const w=typeof r=="string"?r:lf(r.path||"/",r.query||{})+(r.hash||"");if(d!=null&&d.open){const{target:u="_blank",windowFeatures:o={}}=d.open,c=Object.entries(o).filter(([g,p])=>p!==void 0).map(([g,p])=>`${g.toLowerCase()}=${p}`).join(", ");return open(w,u,c),Promise.resolve()}const t=(d==null?void 0:d.external)||yn(w,{acceptRelative:!0});if(t){if(!(d!=null&&d.external))throw new Error("Navigating to an external URL is not allowed by default. Use `navigateTo(url, { external: true })`.");const u=hs(w).protocol;if(u&&Oy(u))throw new Error(`Cannot navigate to a URL with '${u}' protocol.`)}const x=jg();if(!t&&x)return r;const v=qr(),s=It();return t?(s._scope.stop(),d!=null&&d.replace?location.replace(w):location.href=w,x?s.isHydrating?new Promise(()=>{}):!1:Promise.resolve()):d!=null&&d.replace?v.replace(r):v.push(r)},jf="__nuxt_error",pi=()=>wp(It().payload,"error"),ao=r=>{const d=mi(r);try{const w=It(),t=pi();w.hooks.callHook("app:error",d),t.value=t.value||d}catch{throw d}return d},Eg=async(r={})=>{const d=It(),w=pi();d.callHook("app:error:cleared",r),r.redirect&&await qr().replace(r.redirect),w.value=null},Tg=r=>!!r&&typeof r=="object"&&jf in r,mi=r=>{const d=Ta(r);return Object.defineProperty(d,jf,{value:!0,configurable:!1,writable:!1}),d},Mg="modulepreload",kg=function(r,d){return r[0]==="."?new URL(r,d).href:r},rc={},Cg=function(d,w,t){let x=Promise.resolve();if(w&&w.length>0){document.getElementsByTagName("link");const v=document.querySelector("meta[property=csp-nonce]"),s=(v==null?void 0:v.nonce)||(v==null?void 0:v.getAttribute("nonce"));x=Promise.all(w.map(u=>{if(u=kg(u,t),u in rc)return;rc[u]=!0;const o=u.endsWith(".css"),c=o?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${u}"]${c}`))return;const g=document.createElement("link");if(g.rel=o?"stylesheet":Mg,o||(g.as="script",g.crossOrigin=""),g.href=u,s&&g.setAttribute("nonce",s),document.head.appendChild(g),o)return new Promise((p,n)=>{g.addEventListener("load",p),g.addEventListener("error",()=>n(new Error(`Unable to preload CSS for ${u}`)))})}))}return x.then(()=>d()).catch(v=>{const s=new Event("vite:preloadError",{cancelable:!0});if(s.payload=v,window.dispatchEvent(s),!s.defaultPrevented)throw v})},rt=(...r)=>Cg(...r).catch(d=>{const w=new Event("nuxt.preloadError");throw w.payload=d,window.dispatchEvent(w),d}),Og=-1,Pg=-2,Ag=-3,Rg=-4,Lg=-5,Ig=-6;function Dg(r,d){return Fg(JSON.parse(r),d)}function Fg(r,d){if(typeof r=="number")return x(r,!0);if(!Array.isArray(r)||r.length===0)throw new Error("Invalid input");const w=r,t=Array(w.length);function x(v,s=!1){if(v===Og)return;if(v===Ag)return NaN;if(v===Rg)return 1/0;if(v===Lg)return-1/0;if(v===Ig)return-0;if(s)throw new Error("Invalid input");if(v in t)return t[v];const u=w[v];if(!u||typeof u!="object")t[v]=u;else if(Array.isArray(u))if(typeof u[0]=="string"){const o=u[0],c=d==null?void 0:d[o];if(c)return t[v]=c(x(u[1]));switch(o){case"Date":t[v]=new Date(u[1]);break;case"Set":const g=new Set;t[v]=g;for(let i=1;i>>9)+65536).toString(16).substring(1,8).toLowerCase()}function nc(r){return r._h||dl(r._d?r._d:`${r.tag}:${r.textContent||r.innerHTML||""}:${Object.entries(r.props).map(([d,w])=>`${d}:${String(w)}`).join(",")}`)}function Ef(r,d){const{props:w,tag:t}=r;if(Gg.includes(t))return t;if(t==="link"&&w.rel==="canonical")return"canonical";if(w.charset)return"charset";const x=["id"];t==="meta"&&x.push("name","property","http-equiv");for(const v of x)if(typeof w[v]<"u"){const s=String(w[v]);return`${t}:${v}:${s}`}return!1}function oc(r,d){return r==null?d||null:typeof r=="function"?r(d):r}function Tf(r,d){const w=[],t=d.resolveKeyData||(v=>v.key),x=d.resolveValueData||(v=>v.value);for(const[v,s]of Object.entries(r))w.push(...(Array.isArray(s)?s:[s]).map(u=>{const o={key:v,value:u},c=x(o);return typeof c=="object"?Tf(c,d):Array.isArray(c)?c:{[typeof d.key=="function"?d.key(o):d.key]:t(o),[typeof d.value=="function"?d.value(o):d.value]:c}}).flat());return w}function Mf(r,d){return Object.entries(r).map(([w,t])=>{if(typeof t=="object"&&(t=Mf(t,d)),d.resolve){const x=d.resolve({key:w,value:t});if(typeof x<"u")return x}return typeof t=="number"&&(t=t.toString()),typeof t=="string"&&d.wrapValue&&(t=t.replace(new RegExp(d.wrapValue,"g"),`\\${d.wrapValue}`),t=`${d.wrapValue}${t}${d.wrapValue}`),`${w}${d.keyValueSeparator||""}${t}`}).join(d.entrySeparator||"")}const pr=r=>({keyValue:r,metaKey:"property"}),Wi=r=>({keyValue:r}),fl={appleItunesApp:{unpack:{entrySeparator:", ",resolve({key:r,value:d}){return`${hn(r)}=${d}`}}},articleExpirationTime:pr("article:expiration_time"),articleModifiedTime:pr("article:modified_time"),articlePublishedTime:pr("article:published_time"),bookReleaseDate:pr("book:release_date"),charset:{metaKey:"charset"},contentSecurityPolicy:{unpack:{entrySeparator:"; ",resolve({key:r,value:d}){return`${hn(r)} ${d}`}},metaKey:"http-equiv"},contentType:{metaKey:"http-equiv"},defaultStyle:{metaKey:"http-equiv"},fbAppId:pr("fb:app_id"),msapplicationConfig:Wi("msapplication-Config"),msapplicationTileColor:Wi("msapplication-TileColor"),msapplicationTileImage:Wi("msapplication-TileImage"),ogAudioSecureUrl:pr("og:audio:secure_url"),ogAudioUrl:pr("og:audio"),ogImageSecureUrl:pr("og:image:secure_url"),ogImageUrl:pr("og:image"),ogSiteName:pr("og:site_name"),ogVideoSecureUrl:pr("og:video:secure_url"),ogVideoUrl:pr("og:video"),profileFirstName:pr("profile:first_name"),profileLastName:pr("profile:last_name"),profileUsername:pr("profile:username"),refresh:{metaKey:"http-equiv",unpack:{entrySeparator:";",resolve({key:r,value:d}){if(r==="seconds")return`${d}`}}},robots:{unpack:{entrySeparator:", ",resolve({key:r,value:d}){return typeof d=="boolean"?`${hn(r)}`:`${hn(r)}:${d}`}}},xUaCompatible:{metaKey:"http-equiv"}},kf=["og","book","article","profile"];function Cf(r){var w;const d=hn(r).split(":")[0];return kf.includes(d)?"property":((w=fl[r])==null?void 0:w.metaKey)||"name"}function Hg(r){var d;return((d=fl[r])==null?void 0:d.keyValue)||hn(r)}function hn(r){const d=r.replace(/([A-Z])/g,"-$1").toLowerCase(),w=d.split("-")[0];return kf.includes(w)||w==="twitter"?r.replace(/([A-Z])/g,":$1").toLowerCase():d}function ka(r){if(Array.isArray(r))return r.map(w=>ka(w));if(typeof r!="object"||Array.isArray(r))return r;const d={};for(const[w,t]of Object.entries(r))d[hn(w)]=ka(t);return d}function zg(r,d){const w=fl[d];return d==="refresh"?`${r.seconds};url=${r.url}`:Mf(ka(r),{keyValueSeparator:"=",entrySeparator:", ",resolve({value:t,key:x}){if(t===null)return"";if(typeof t=="boolean")return`${x}`},...w==null?void 0:w.unpack})}const Of=["og:image","og:video","og:audio","twitter:image"];function Pf(r){const d={};return Object.entries(r).forEach(([w,t])=>{String(t)!=="false"&&w&&(d[w]=t)}),d}function sc(r,d){const w=Pf(d),t=hn(r),x=Cf(t);if(Of.includes(t)){const v={};return Object.entries(w).forEach(([s,u])=>{v[`${r}${s==="url"?"":`${s.charAt(0).toUpperCase()}${s.slice(1)}`}`]=u}),hl(v).sort((s,u)=>{var o,c;return(((o=s[x])==null?void 0:o.length)||0)-(((c=u[x])==null?void 0:c.length)||0)})}return[{[x]:t,...w}]}function hl(r){const d=[],w={};Object.entries(r).forEach(([x,v])=>{if(!Array.isArray(v)){if(typeof v=="object"&&v){if(Of.includes(hn(x))){d.push(...sc(x,v));return}w[x]=Pf(v)}else w[x]=v;return}v.forEach(s=>{d.push(...typeof s=="string"?hl({[x]:s}):sc(x,s))})});const t=Tf(w,{key({key:x}){return Cf(x)},value({key:x}){return x==="charset"?"charset":"content"},resolveKeyData({key:x}){return Hg(x)},resolveValueData({value:x,key:v}){return x===null?"_null":typeof x=="object"?zg(x,v):typeof x=="number"?x.toString():x}});return[...d,...t].map(x=>(x.content==="_null"&&(x.content=null),x))}async function Wg(r,d,w){const t={tag:r,props:await Af(typeof d=="object"&&typeof d!="function"&&!(d instanceof Promise)?{...d}:{[["script","noscript","style"].includes(r)?"innerHTML":"textContent"]:d},["templateParams","titleTemplate"].includes(r))};return Sf.forEach(x=>{const v=typeof t.props[x]<"u"?t.props[x]:w[x];typeof v<"u"&&((!["innerHTML","textContent","children"].includes(x)||Ug.includes(t.tag))&&(t[x==="children"?"innerHTML":x]=v),delete t.props[x])}),t.props.body&&(t.tagPosition="bodyClose",delete t.props.body),t.tag==="script"&&typeof t.innerHTML=="object"&&(t.innerHTML=JSON.stringify(t.innerHTML),t.props.type=t.props.type||"application/json"),Array.isArray(t.props.content)?t.props.content.map(x=>({...t,props:{...t.props,content:x}})):t}function qg(r,d){var t;const w=r==="class"?" ":";";return typeof d=="object"&&!Array.isArray(d)&&(d=Object.entries(d).filter(([,x])=>x).map(([x,v])=>r==="style"?`${x}:${v}`:x)),(t=Array.isArray(d)?d.join(w):d)==null?void 0:t.split(w).filter(x=>x.trim()).filter(Boolean).join(w)}async function Af(r,d){for(const w of Object.keys(r)){if(["class","style"].includes(w)){r[w]=qg(w,r[w]);continue}if(r[w]instanceof Promise&&(r[w]=await r[w]),!d&&!Sf.includes(w)){const t=String(r[w]),x=w.startsWith("data-");t==="true"||t===""?r[w]=x?"true":!0:r[w]||(x&&t==="false"?r[w]="false":delete r[w])}}return r}const Xg=10;async function Yg(r){const d=[];return Object.entries(r.resolvedInput).filter(([w,t])=>typeof t<"u"&&Bg.includes(w)).forEach(([w,t])=>{const x=Ng(t);d.push(...x.map(v=>Wg(w,v,r)).flat())}),(await Promise.all(d)).flat().filter(Boolean).map((w,t)=>(w._e=r._i,r.mode&&(w._m=r.mode),w._p=(r._i<o&&o[c]||void 0,d):u=d[s],typeof u<"u"?(u||"").replace(/"/g,'\\"'):!1}let x=r;try{x=decodeURI(r)}catch{}return(x.match(/%(\w+\.+\w+)|%(\w+)/g)||[]).sort().reverse().forEach(s=>{const u=t(s.slice(1));typeof u=="string"&&(r=r.replace(new RegExp(`\\${s}(\\W|$)`,"g"),(o,c)=>`${u}${c}`).trim())}),r.includes(En)&&(r.endsWith(En)&&(r=r.slice(0,-En.length).trim()),r.startsWith(En)&&(r=r.slice(En.length).trim()),r=r.replace(new RegExp(`\\${En}\\s*\\${En}`,"g"),En),r=Us(r,{separator:w},w)),r}async function Rf(r,d={}){var g;const w=d.document||r.resolvedOptions.document;if(!w||!r.dirty)return;const t={shouldRender:!0,tags:[]};if(await r.hooks.callHook("dom:beforeRender",t),!t.shouldRender)return;const x=(await r.resolveTags()).map(p=>({tag:p,id:Ns.includes(p.tag)?nc(p):p.tag,shouldRender:!0}));let v=r._dom;if(!v){v={elMap:{htmlAttrs:w.documentElement,bodyAttrs:w.body}};for(const p of["body","head"]){const n=(g=w[p])==null?void 0:g.children,i=[];for(const a of[...n].filter(h=>Ns.includes(h.tagName.toLowerCase()))){const h={tag:a.tagName.toLowerCase(),props:await Af(a.getAttributeNames().reduce((f,m)=>({...f,[m]:a.getAttribute(m)}),{})),innerHTML:a.innerHTML};let y=1,l=Ef(h);for(;l&&i.find(f=>f._d===l);)l=`${l}:${y++}`;h._d=l||void 0,i.push(h),v.elMap[a.getAttribute("data-hid")||nc(h)]=a}}}v.pendingSideEffects={...v.sideEffects||{}},v.sideEffects={};function s(p,n,i){const a=`${p}:${n}`;v.sideEffects[a]=i,delete v.pendingSideEffects[a]}function u({id:p,$el:n,tag:i}){const a=i.tag.endsWith("Attrs");v.elMap[p]=n,a||(["textContent","innerHTML"].forEach(h=>{i[h]&&i[h]!==n[h]&&(n[h]=i[h])}),s(p,"el",()=>{var h;(h=v.elMap[p])==null||h.remove(),delete v.elMap[p]}));for(const[h,y]of Object.entries(i._eventHandlers||{}))n.getAttribute(`data-${h}`)!==""&&((i.tag==="bodyAttrs"?w.defaultView:n).addEventListener(h.replace("on",""),y.bind(n)),n.setAttribute(`data-${h}`,""));Object.entries(i.props).forEach(([h,y])=>{const l=`attr:${h}`;if(h==="class")for(const f of(y||"").split(" ").filter(Boolean))a&&s(p,`${l}:${f}`,()=>n.classList.remove(f)),!n.classList.contains(f)&&n.classList.add(f);else if(h==="style")for(const f of(y||"").split(";").filter(Boolean)){const[m,...b]=f.split(":").map(j=>j.trim());s(p,`${l}:${f}:${m}`,()=>{n.style.removeProperty(m)}),n.style.setProperty(m,b.join(":"))}else n.getAttribute(h)!==y&&n.setAttribute(h,y===!0?"":String(y)),a&&s(p,l,()=>n.removeAttribute(h))})}const o=[],c={bodyClose:void 0,bodyOpen:void 0,head:void 0};for(const p of x){const{tag:n,shouldRender:i,id:a}=p;if(i){if(n.tag==="title"){w.title=n.textContent;continue}p.$el=p.$el||v.elMap[a],p.$el?u(p):Ns.includes(n.tag)&&o.push(p)}}for(const p of o){const n=p.tag.tagPosition||"head";p.$el=w.createElement(p.tag.tag),u(p),c[n]=c[n]||w.createDocumentFragment(),c[n].appendChild(p.$el)}for(const p of x)await r.hooks.callHook("dom:renderTag",p,w,s);c.head&&w.head.appendChild(c.head),c.bodyOpen&&w.body.insertBefore(c.bodyOpen,w.body.firstChild),c.bodyClose&&w.body.appendChild(c.bodyClose),Object.values(v.pendingSideEffects).forEach(p=>p()),r._dom=v,r.dirty=!1,await r.hooks.callHook("dom:rendered",{renders:x})}async function Zg(r,d={}){const w=d.delayFn||(t=>setTimeout(t,10));return r._domUpdatePromise=r._domUpdatePromise||new Promise(t=>w(async()=>{await Rf(r,d),delete r._domUpdatePromise,t()}))}function Kg(r){return d=>{var t,x;const w=((x=(t=d.resolvedOptions.document)==null?void 0:t.head.querySelector('script[id="unhead:payload"]'))==null?void 0:x.innerHTML)||!1;return w&&d.push(JSON.parse(w)),{mode:"client",hooks:{"entries:updated":function(v){Zg(v,r)}}}}}const Qg=["templateParams","htmlAttrs","bodyAttrs"],Jg={hooks:{"tag:normalise":function({tag:r}){["hid","vmid","key"].forEach(t=>{r.props[t]&&(r.key=r.props[t],delete r.props[t])});const w=Ef(r)||(r.key?`${r.tag}:${r.key}`:!1);w&&(r._d=w)},"tags:resolve":function(r){const d={};r.tags.forEach(t=>{const x=(t.key?`${t.tag}:${t.key}`:t._d)||t._p,v=d[x];if(v){let u=t==null?void 0:t.tagDuplicateStrategy;if(!u&&Qg.includes(t.tag)&&(u="merge"),u==="merge"){const o=v.props;["class","style"].forEach(c=>{o[c]&&(t.props[c]?(c==="style"&&!o[c].endsWith(";")&&(o[c]+=";"),t.props[c]=`${o[c]} ${t.props[c]}`):t.props[c]=o[c])}),d[x].props={...o,...t.props};return}else if(t._e===v._e){v._duped=v._duped||[],t._d=`${v._d}:${v._duped.length+1}`,v._duped.push(t);return}else if(ei(t)>ei(v))return}const s=Object.keys(t.props).length+(t.innerHTML?1:0)+(t.textContent?1:0);if(Ns.includes(t.tag)&&s===0){delete d[x];return}d[x]=t});const w=[];Object.values(d).forEach(t=>{const x=t._duped;delete t._duped,w.push(t),x&&w.push(...x)}),r.tags=w,r.tags=r.tags.filter(t=>!(t.tag==="meta"&&(t.props.name||t.props.property)&&!t.props.content))}}},e0={mode:"server",hooks:{"tags:resolve":function(r){const d={};r.tags.filter(w=>["titleTemplate","templateParams","title"].includes(w.tag)&&w._m==="server").forEach(w=>{d[w.tag]=w.tag.startsWith("title")?w.textContent:w.props}),Object.keys(d).length&&r.tags.push({tag:"script",innerHTML:JSON.stringify(d),props:{id:"unhead:payload",type:"application/json"}})}}},t0=["script","link","bodyAttrs"],r0=r=>({hooks:{"tags:resolve":function(d){for(const w of d.tags.filter(t=>t0.includes(t.tag)))Object.entries(w.props).forEach(([t,x])=>{t.startsWith("on")&&typeof x=="function"&&(r.ssr&&lc.includes(t)?w.props[t]=`this.dataset.${t}fired = true`:delete w.props[t],w._eventHandlers=w._eventHandlers||{},w._eventHandlers[t]=x)}),r.ssr&&w._eventHandlers&&(w.props.src||w.props.href)&&(w.key=w.key||dl(w.props.src||w.props.href))},"dom:renderTag":function({$el:d,tag:w}){var t,x;for(const v of Object.keys((d==null?void 0:d.dataset)||{}).filter(s=>lc.some(u=>`${u}fired`===s))){const s=v.replace("fired","");(x=(t=w._eventHandlers)==null?void 0:t[s])==null||x.call(d,new Event(s.replace("on","")))}}}}),n0=["link","style","script","noscript"],o0={hooks:{"tag:normalise":({tag:r})=>{r.key&&n0.includes(r.tag)&&(r.props["data-hid"]=r._h=dl(r.key))}}},s0={hooks:{"tags:resolve":r=>{const d=w=>{var t;return(t=r.tags.find(x=>x._d===w))==null?void 0:t._p};for(const{prefix:w,offset:t}of $g)for(const x of r.tags.filter(v=>typeof v.tagPriority=="string"&&v.tagPriority.startsWith(w))){const v=d(x.tagPriority.replace(w,""));typeof v<"u"&&(x._p=v+t)}r.tags.sort((w,t)=>w._p-t._p).sort((w,t)=>ei(w)-ei(t))}}},i0={meta:"content",link:"href",htmlAttrs:"lang"},a0=r=>({hooks:{"tags:resolve":d=>{var u;const{tags:w}=d,t=(u=w.find(o=>o.tag==="title"))==null?void 0:u.textContent,x=w.findIndex(o=>o.tag==="templateParams"),v=x!==-1?w[x].props:{},s=v.separator||"|";delete v.separator,v.pageTitle=Us(v.pageTitle||t||"",v,s);for(const o of w.filter(c=>c.processTemplateParams!==!1)){const c=i0[o.tag];c&&typeof o.props[c]=="string"?o.props[c]=Us(o.props[c],v,s):(o.processTemplateParams===!0||["titleTemplate","title"].includes(o.tag))&&["innerHTML","textContent"].forEach(g=>{typeof o[g]=="string"&&(o[g]=Us(o[g],v,s))})}r._templateParams=v,r._separator=s,d.tags=w.filter(o=>o.tag!=="templateParams")}}}),l0={hooks:{"tags:resolve":r=>{const{tags:d}=r;let w=d.findIndex(x=>x.tag==="titleTemplate");const t=d.findIndex(x=>x.tag==="title");if(t!==-1&&w!==-1){const x=oc(d[w].textContent,d[t].textContent);x!==null?d[t].textContent=x||d[t].textContent:delete d[t]}else if(w!==-1){const x=oc(d[w].textContent);x!==null&&(d[w].textContent=x,d[w].tag="title",w=-1)}w!==-1&&delete d[w],r.tags=d.filter(Boolean)}}},u0={hooks:{"tags:afterResolve":function(r){for(const d of r.tags)typeof d.innerHTML=="string"&&(d.innerHTML&&["application/ld+json","application/json"].includes(d.props.type)?d.innerHTML=d.innerHTML.replace(/{u.dirty=!0,d.callHook("entries:updated",u)};let x=0,v=[];const s=[],u={plugins:s,dirty:!1,resolvedOptions:r,hooks:d,headEntries(){return v},use(o){const c=typeof o=="function"?o(u):o;(!c.key||!s.some(g=>g.key===c.key))&&(s.push(c),uc(c.mode,w)&&d.addHooks(c.hooks||{}))},push(o,c){c==null||delete c.head;const g={_i:x++,input:o,...c};return uc(g.mode,w)&&(v.push(g),t()),{dispose(){v=v.filter(p=>p._i!==g._i),d.callHook("entries:updated",u),t()},patch(p){v=v.map(n=>(n._i===g._i&&(n.input=g.input=p),n)),t()}}},async resolveTags(){const o={tags:[],entries:[...v]};await d.callHook("entries:resolve",o);for(const c of o.entries){const g=c.resolvedInput||c.input;if(c.resolvedInput=await(c.transform?c.transform(g):g),c.resolvedInput)for(const p of await Yg(c)){const n={tag:p,entry:c,resolvedOptions:u.resolvedOptions};await d.callHook("tag:normalise",n),o.tags.push(n.tag)}}return await d.callHook("tags:beforeResolve",o),await d.callHook("tags:resolve",o),await d.callHook("tags:afterResolve",o),o.tags},ssr:w};return[Jg,e0,r0,o0,s0,a0,l0,u0,...(r==null?void 0:r.plugins)||[]].forEach(o=>u.use(o)),u.hooks.callHook("init",u),u}function f0(){return Lf}const h0=tf.startsWith("3");function p0(r){return typeof r=="function"?r():Bt(r)}function ti(r,d=""){if(r instanceof Promise)return r;const w=p0(r);return!r||!w?w:Array.isArray(w)?w.map(t=>ti(t,d)):typeof w=="object"?Object.fromEntries(Object.entries(w).map(([t,x])=>t==="titleTemplate"||t.startsWith("on")?[t,Bt(x)]:[t,ti(x,t)])):w}const m0={hooks:{"entries:resolve":function(r){for(const d of r.entries)d.resolvedInput=ti(d.input)}}},If="usehead";function y0(r){return{install(w){h0&&(w.config.globalProperties.$unhead=r,w.config.globalProperties.$head=r,w.provide(If,r))}}.install}function g0(r={}){r.domDelayFn=r.domDelayFn||(w=>Ur(()=>setTimeout(()=>w(),0)));const d=c0(r);return d.use(m0),d.install=y0(d),d}const Ca=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},Oa="__unhead_injection_handler__";function v0(r){Ca[Oa]=r}function b0(){if(Oa in Ca)return Ca[Oa]();const r=Ht(If);return r||f0()}function _0(r,d={}){const w=d.head||b0();if(w)return w.ssr?w.push(r,d):w0(w,r,d)}function w0(r,d,w={}){const t=mt(!1),x=mt({});ln(()=>{x.value=t.value?{}:ti(d)});const v=r.push(x.value,w);return In(x,u=>{v.patch(u)}),So()&&(ls(()=>{v.dispose()}),kd(()=>{t.value=!0}),Md(()=>{t.value=!1})),v}function x0(r,d){const{title:w,titleTemplate:t,...x}=r;return _0({title:w,titleTemplate:t,_flatMeta:x},{...d,transform(v){const s=hl({...v._flatMeta});return delete v._flatMeta,{...v,meta:s}}})}const j0={nuxt:{buildId:"d6ca5b55-ea93-45cf-9a93-ac870132a3e2"}},S0=gg(j0);function Df(){const r=It();return r._appConfig||(r._appConfig=Un(S0)),r._appConfig}const E0=!1,Pa=!1,T0=!1,M0={componentName:"NuxtLink"},R_={deep:!0},L_={},k0="#__nuxt";let Bs,Ff;function C0(){var d;const r=(d=Df().nuxt)==null?void 0:d.buildId;return Bs=$fetch(cl(`builds/meta/${r}.json`)),Bs.then(w=>{Ff=yg(w.matcher)}),Bs}function yi(){return Bs||C0()}async function pl(r){return await yi(),_f({},...Ff.matchAll(r).reverse())}function cc(r,d={}){const w=P0(r,d),t=It(),x=t._payloadCache=t._payloadCache||{};return w in x||(x[w]=A0(r).then(v=>v?Nf(w).then(s=>s||(delete x[w],null)):(x[w]=null,null))),x[w]}const O0="_payload.json";function P0(r,d={}){var x;const w=new URL(r,"http://localhost");if(w.host!=="localhost"||yn(w.pathname,{acceptRelative:!0}))throw new Error("Payload URL must not include hostname: "+r);const t=d.hash||(d.fresh?Date.now():(x=Df().nuxt)==null?void 0:x.buildId);return di(fi().app.baseURL,w.pathname,O0+(t?`?${t}`:""))}async function Nf(r){const d=fetch(r).then(w=>w.text().then(Uf));try{return await d}catch(w){console.warn("[nuxt] Cannot load payload ",r,w)}return null}async function A0(r=hi().path){if(r=ci(r),(await yi()).prerendered.includes(r))return!0;const w=await pl(r);return!!w.prerender&&!w.redirect}let Ps=null;async function R0(){if(Ps)return Ps;const r=document.getElementById("__NUXT_DATA__");if(!r)return{};const d=await Uf(r.textContent||""),w=r.dataset.src?await Nf(r.dataset.src):void 0;return Ps={...d,...w,...window.__NUXT__},Ps}async function Uf(r){return await Dg(r,It()._payloadRevivers)}function L0(r,d){It()._payloadRevivers[r]=d}const dc={NuxtError:r=>mi(r),EmptyShallowRef:r=>Zo(r==="_"?void 0:r==="0n"?BigInt(0):$s(r)),EmptyRef:r=>mt(r==="_"?void 0:r==="0n"?BigInt(0):$s(r)),ShallowRef:r=>Zo(r),ShallowReactive:r=>is(r),Ref:r=>mt(r),Reactive:r=>Un(r)},I0=gn({name:"nuxt:revive-payload:client",order:-30,async setup(r){let d,w;for(const t in dc)L0(t,dc[t]);Object.assign(r.payload,([d,w]=ts(()=>r.runWithContext(R0)),d=await d,w(),d)),window.__NUXT__=r.payload}}),D0=[],F0=gn({name:"nuxt:head",enforce:"pre",setup(r){const d=g0({plugins:D0});v0(()=>It().vueApp._context.provides.usehead),r.vueApp.use(d);{let w=!0;const t=async()=>{w=!1,await Rf(d)};d.hooks.hook("dom:beforeRender",x=>{x.shouldRender=!w}),r.hooks.hook("page:start",()=>{w=!0}),r.hooks.hook("page:finish",()=>{r.isHydrating||t()}),r.hooks.hook("app:error",t),r.hooks.hook("app:suspense:resolve",t)}}});/*! + * vue-router v4.3.2 + * (c) 2024 Eduardo San Martin Morote + * @license MIT + */const io=typeof document<"u";function N0(r){return r.__esModule||r[Symbol.toStringTag]==="Module"}const xt=Object.assign;function qi(r,d){const w={};for(const t in d){const x=d[t];w[t]=Jr(x)?x.map(r):r(x)}return w}const qo=()=>{},Jr=Array.isArray,Bf=/#/g,U0=/&/g,B0=/\//g,G0=/=/g,V0=/\?/g,Gf=/\+/g,H0=/%5B/g,z0=/%5D/g,Vf=/%5E/g,W0=/%60/g,Hf=/%7B/g,q0=/%7C/g,zf=/%7D/g,X0=/%20/g;function ml(r){return encodeURI(""+r).replace(q0,"|").replace(H0,"[").replace(z0,"]")}function Y0(r){return ml(r).replace(Hf,"{").replace(zf,"}").replace(Vf,"^")}function Aa(r){return ml(r).replace(Gf,"%2B").replace(X0,"+").replace(Bf,"%23").replace(U0,"%26").replace(W0,"`").replace(Hf,"{").replace(zf,"}").replace(Vf,"^")}function $0(r){return Aa(r).replace(G0,"%3D")}function Z0(r){return ml(r).replace(Bf,"%23").replace(V0,"%3F")}function K0(r){return r==null?"":Z0(r).replace(B0,"%2F")}function rs(r){try{return decodeURIComponent(""+r)}catch{}return""+r}const Q0=/\/$/,J0=r=>r.replace(Q0,"");function Xi(r,d,w="/"){let t,x={},v="",s="";const u=d.indexOf("#");let o=d.indexOf("?");return u=0&&(o=-1),o>-1&&(t=d.slice(0,o),v=d.slice(o+1,u>-1?u:d.length),x=r(v)),u>-1&&(t=t||d.slice(0,u),s=d.slice(u,d.length)),t=nv(t??d,w),{fullPath:t+(v&&"?")+v+s,path:t,query:x,hash:rs(s)}}function ev(r,d){const w=d.query?r(d.query):"";return d.path+(w&&"?")+w+(d.hash||"")}function fc(r,d){return!d||!r.toLowerCase().startsWith(d.toLowerCase())?r:r.slice(d.length)||"/"}function tv(r,d,w){const t=d.matched.length-1,x=w.matched.length-1;return t>-1&&t===x&&_o(d.matched[t],w.matched[x])&&Wf(d.params,w.params)&&r(d.query)===r(w.query)&&d.hash===w.hash}function _o(r,d){return(r.aliasOf||r)===(d.aliasOf||d)}function Wf(r,d){if(Object.keys(r).length!==Object.keys(d).length)return!1;for(const w in r)if(!rv(r[w],d[w]))return!1;return!0}function rv(r,d){return Jr(r)?hc(r,d):Jr(d)?hc(d,r):r===d}function hc(r,d){return Jr(d)?r.length===d.length&&r.every((w,t)=>w===d[t]):r.length===1&&r[0]===d}function nv(r,d){if(r.startsWith("/"))return r;if(!r)return d;const w=d.split("/"),t=r.split("/"),x=t[t.length-1];(x===".."||x===".")&&t.push("");let v=w.length-1,s,u;for(s=0;s1&&v--;else break;return w.slice(0,v).join("/")+"/"+t.slice(s).join("/")}var ns;(function(r){r.pop="pop",r.push="push"})(ns||(ns={}));var Xo;(function(r){r.back="back",r.forward="forward",r.unknown=""})(Xo||(Xo={}));function ov(r){if(!r)if(io){const d=document.querySelector("base");r=d&&d.getAttribute("href")||"/",r=r.replace(/^\w+:\/\/[^\/]+/,"")}else r="/";return r[0]!=="/"&&r[0]!=="#"&&(r="/"+r),J0(r)}const sv=/^[^#]+#/;function iv(r,d){return r.replace(sv,"#")+d}function av(r,d){const w=document.documentElement.getBoundingClientRect(),t=r.getBoundingClientRect();return{behavior:d.behavior,left:t.left-w.left-(d.left||0),top:t.top-w.top-(d.top||0)}}const gi=()=>({left:window.scrollX,top:window.scrollY});function lv(r){let d;if("el"in r){const w=r.el,t=typeof w=="string"&&w.startsWith("#"),x=typeof w=="string"?t?document.getElementById(w.slice(1)):document.querySelector(w):w;if(!x)return;d=av(x,r)}else d=r;"scrollBehavior"in document.documentElement.style?window.scrollTo(d):window.scrollTo(d.left!=null?d.left:window.scrollX,d.top!=null?d.top:window.scrollY)}function pc(r,d){return(history.state?history.state.position-d:-1)+r}const Ra=new Map;function uv(r,d){Ra.set(r,d)}function cv(r){const d=Ra.get(r);return Ra.delete(r),d}let dv=()=>location.protocol+"//"+location.host;function qf(r,d){const{pathname:w,search:t,hash:x}=d,v=r.indexOf("#");if(v>-1){let u=x.includes(r.slice(v))?r.slice(v).length:1,o=x.slice(u);return o[0]!=="/"&&(o="/"+o),fc(o,"")}return fc(w,r)+t+x}function fv(r,d,w,t){let x=[],v=[],s=null;const u=({state:n})=>{const i=qf(r,location),a=w.value,h=d.value;let y=0;if(n){if(w.value=i,d.value=n,s&&s===a){s=null;return}y=h?n.position-h.position:0}else t(i);x.forEach(l=>{l(w.value,a,{delta:y,type:ns.pop,direction:y?y>0?Xo.forward:Xo.back:Xo.unknown})})};function o(){s=w.value}function c(n){x.push(n);const i=()=>{const a=x.indexOf(n);a>-1&&x.splice(a,1)};return v.push(i),i}function g(){const{history:n}=window;n.state&&n.replaceState(xt({},n.state,{scroll:gi()}),"")}function p(){for(const n of v)n();v=[],window.removeEventListener("popstate",u),window.removeEventListener("beforeunload",g)}return window.addEventListener("popstate",u),window.addEventListener("beforeunload",g,{passive:!0}),{pauseListeners:o,listen:c,destroy:p}}function mc(r,d,w,t=!1,x=!1){return{back:r,current:d,forward:w,replaced:t,position:window.history.length,scroll:x?gi():null}}function hv(r){const{history:d,location:w}=window,t={value:qf(r,w)},x={value:d.state};x.value||v(t.value,{back:null,current:t.value,forward:null,position:d.length-1,replaced:!0,scroll:null},!0);function v(o,c,g){const p=r.indexOf("#"),n=p>-1?(w.host&&document.querySelector("base")?r:r.slice(p))+o:dv()+r+o;try{d[g?"replaceState":"pushState"](c,"",n),x.value=c}catch(i){console.error(i),w[g?"replace":"assign"](n)}}function s(o,c){const g=xt({},d.state,mc(x.value.back,o,x.value.forward,!0),c,{position:x.value.position});v(o,g,!0),t.value=o}function u(o,c){const g=xt({},x.value,d.state,{forward:o,scroll:gi()});v(g.current,g,!0);const p=xt({},mc(t.value,o,null),{position:g.position+1},c);v(o,p,!1),t.value=o}return{location:t,state:x,push:u,replace:s}}function Xf(r){r=ov(r);const d=hv(r),w=fv(r,d.state,d.location,d.replace);function t(v,s=!0){s||w.pauseListeners(),history.go(v)}const x=xt({location:"",base:r,go:t,createHref:iv.bind(null,r)},d,w);return Object.defineProperty(x,"location",{enumerable:!0,get:()=>d.location.value}),Object.defineProperty(x,"state",{enumerable:!0,get:()=>d.state.value}),x}function pv(r){return r=location.host?r||location.pathname+location.search:"",r.includes("#")||(r+="#"),Xf(r)}function mv(r){return typeof r=="string"||r&&typeof r=="object"}function Yf(r){return typeof r=="string"||typeof r=="symbol"}const Zr={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0},$f=Symbol("");var yc;(function(r){r[r.aborted=4]="aborted",r[r.cancelled=8]="cancelled",r[r.duplicated=16]="duplicated"})(yc||(yc={}));function wo(r,d){return xt(new Error,{type:r,[$f]:!0},d)}function fn(r,d){return r instanceof Error&&$f in r&&(d==null||!!(r.type&d))}const gc="[^/]+?",yv={sensitive:!1,strict:!1,start:!0,end:!0},gv=/[.+*?^${}()[\]/\\]/g;function vv(r,d){const w=xt({},yv,d),t=[];let x=w.start?"^":"";const v=[];for(const c of r){const g=c.length?[]:[90];w.strict&&!c.length&&(x+="/");for(let p=0;pd.length?d.length===1&&d[0]===80?1:-1:0}function _v(r,d){let w=0;const t=r.score,x=d.score;for(;w0&&d[d.length-1]<0}const wv={type:0,value:""},xv=/[a-zA-Z0-9_]/;function jv(r){if(!r)return[[]];if(r==="/")return[[wv]];if(!r.startsWith("/"))throw new Error(`Invalid path "${r}"`);function d(i){throw new Error(`ERR (${w})/"${c}": ${i}`)}let w=0,t=w;const x=[];let v;function s(){v&&x.push(v),v=[]}let u=0,o,c="",g="";function p(){c&&(w===0?v.push({type:0,value:c}):w===1||w===2||w===3?(v.length>1&&(o==="*"||o==="+")&&d(`A repeatable param (${c}) must be alone in its segment. eg: '/:ids+.`),v.push({type:1,value:c,regexp:g,repeatable:o==="*"||o==="+",optional:o==="*"||o==="?"})):d("Invalid state to consume buffer"),c="")}function n(){c+=o}for(;u{s(f)}:qo}function s(g){if(Yf(g)){const p=t.get(g);p&&(t.delete(g),w.splice(w.indexOf(p),1),p.children.forEach(s),p.alias.forEach(s))}else{const p=w.indexOf(g);p>-1&&(w.splice(p,1),g.record.name&&t.delete(g.record.name),g.children.forEach(s),g.alias.forEach(s))}}function u(){return w}function o(g){let p=0;for(;p=0&&(g.record.path!==w[p].record.path||!Zf(g,w[p]));)p++;w.splice(p,0,g),g.record.name&&!_c(g)&&t.set(g.record.name,g)}function c(g,p){let n,i={},a,h;if("name"in g&&g.name){if(n=t.get(g.name),!n)throw wo(1,{location:g});h=n.record.name,i=xt(bc(p.params,n.keys.filter(f=>!f.optional).concat(n.parent?n.parent.keys.filter(f=>f.optional):[]).map(f=>f.name)),g.params&&bc(g.params,n.keys.map(f=>f.name))),a=n.stringify(i)}else if(g.path!=null)a=g.path,n=w.find(f=>f.re.test(a)),n&&(i=n.parse(a),h=n.record.name);else{if(n=p.name?t.get(p.name):w.find(f=>f.re.test(p.path)),!n)throw wo(1,{location:g,currentLocation:p});h=n.record.name,i=xt({},p.params,g.params),a=n.stringify(i)}const y=[];let l=n;for(;l;)y.unshift(l.record),l=l.parent;return{name:h,path:a,params:i,matched:y,meta:kv(y)}}return r.forEach(g=>v(g)),{addRoute:v,resolve:c,removeRoute:s,getRoutes:u,getRecordMatcher:x}}function bc(r,d){const w={};for(const t of d)t in r&&(w[t]=r[t]);return w}function Tv(r){return{path:r.path,redirect:r.redirect,name:r.name,meta:r.meta||{},aliasOf:void 0,beforeEnter:r.beforeEnter,props:Mv(r),children:r.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in r?r.components||null:r.component&&{default:r.component}}}function Mv(r){const d={},w=r.props||!1;if("component"in r)d.default=w;else for(const t in r.components)d[t]=typeof w=="object"?w[t]:w;return d}function _c(r){for(;r;){if(r.record.aliasOf)return!0;r=r.parent}return!1}function kv(r){return r.reduce((d,w)=>xt(d,w.meta),{})}function wc(r,d){const w={};for(const t in r)w[t]=t in d?d[t]:r[t];return w}function Zf(r,d){return d.children.some(w=>w===r||Zf(r,w))}function Cv(r){const d={};if(r===""||r==="?")return d;const t=(r[0]==="?"?r.slice(1):r).split("&");for(let x=0;xv&&Aa(v)):[t&&Aa(t)]).forEach(v=>{v!==void 0&&(d+=(d.length?"&":"")+w,v!=null&&(d+="="+v))})}return d}function Ov(r){const d={};for(const w in r){const t=r[w];t!==void 0&&(d[w]=Jr(t)?t.map(x=>x==null?null:""+x):t==null?t:""+t)}return d}const Pv=Symbol(""),jc=Symbol(""),yl=Symbol(""),gl=Symbol(""),La=Symbol("");function Do(){let r=[];function d(t){return r.push(t),()=>{const x=r.indexOf(t);x>-1&&r.splice(x,1)}}function w(){r=[]}return{add:d,list:()=>r.slice(),reset:w}}function On(r,d,w,t,x,v=s=>s()){const s=t&&(t.enterCallbacks[x]=t.enterCallbacks[x]||[]);return()=>new Promise((u,o)=>{const c=n=>{n===!1?o(wo(4,{from:w,to:d})):n instanceof Error?o(n):mv(n)?o(wo(2,{from:d,to:n})):(s&&t.enterCallbacks[x]===s&&typeof n=="function"&&s.push(n),u())},g=v(()=>r.call(t&&t.instances[x],d,w,c));let p=Promise.resolve(g);r.length<3&&(p=p.then(c)),p.catch(n=>o(n))})}function Yi(r,d,w,t,x=v=>v()){const v=[];for(const s of r)for(const u in s.components){let o=s.components[u];if(!(d!=="beforeRouteEnter"&&!s.instances[u]))if(Av(o)){const g=(o.__vccOpts||o)[d];g&&v.push(On(g,w,t,s,u,x))}else{let c=o();v.push(()=>c.then(g=>{if(!g)return Promise.reject(new Error(`Couldn't resolve component "${u}" at "${s.path}"`));const p=N0(g)?g.default:g;s.components[u]=p;const i=(p.__vccOpts||p)[d];return i&&On(i,w,t,s,u,x)()}))}}return v}function Av(r){return typeof r=="object"||"displayName"in r||"props"in r||"__vccOpts"in r}function Sc(r){const d=Ht(yl),w=Ht(gl),t=jt(()=>{const o=Bt(r.to);return d.resolve(o)}),x=jt(()=>{const{matched:o}=t.value,{length:c}=o,g=o[c-1],p=w.matched;if(!g||!p.length)return-1;const n=p.findIndex(_o.bind(null,g));if(n>-1)return n;const i=Ec(o[c-2]);return c>1&&Ec(g)===i&&p[p.length-1].path!==i?p.findIndex(_o.bind(null,o[c-2])):n}),v=jt(()=>x.value>-1&&Dv(w.params,t.value.params)),s=jt(()=>x.value>-1&&x.value===w.matched.length-1&&Wf(w.params,t.value.params));function u(o={}){return Iv(o)?d[Bt(r.replace)?"replace":"push"](Bt(r.to)).catch(qo):Promise.resolve()}return{route:t,href:jt(()=>t.value.href),isActive:v,isExactActive:s,navigate:u}}const Rv=hr({name:"RouterLink",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"}},useLink:Sc,setup(r,{slots:d}){const w=Un(Sc(r)),{options:t}=Ht(yl),x=jt(()=>({[Tc(r.activeClass,t.linkActiveClass,"router-link-active")]:w.isActive,[Tc(r.exactActiveClass,t.linkExactActiveClass,"router-link-exact-active")]:w.isExactActive}));return()=>{const v=d.default&&d.default(w);return r.custom?v:tr("a",{"aria-current":w.isExactActive?r.ariaCurrentValue:null,href:w.href,onClick:w.navigate,class:x.value},v)}}}),Lv=Rv;function Iv(r){if(!(r.metaKey||r.altKey||r.ctrlKey||r.shiftKey)&&!r.defaultPrevented&&!(r.button!==void 0&&r.button!==0)){if(r.currentTarget&&r.currentTarget.getAttribute){const d=r.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(d))return}return r.preventDefault&&r.preventDefault(),!0}}function Dv(r,d){for(const w in d){const t=d[w],x=r[w];if(typeof t=="string"){if(t!==x)return!1}else if(!Jr(x)||x.length!==t.length||t.some((v,s)=>v!==x[s]))return!1}return!0}function Ec(r){return r?r.aliasOf?r.aliasOf.path:r.path:""}const Tc=(r,d,w)=>r??d??w,Fv=hr({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(r,{attrs:d,slots:w}){const t=Ht(La),x=jt(()=>r.route||t.value),v=Ht(jc,0),s=jt(()=>{let c=Bt(v);const{matched:g}=x.value;let p;for(;(p=g[c])&&!p.components;)c++;return c}),u=jt(()=>x.value.matched[s.value]);Wr(jc,jt(()=>s.value+1)),Wr(Pv,u),Wr(La,x);const o=mt();return In(()=>[o.value,u.value,r.name],([c,g,p],[n,i,a])=>{g&&(g.instances[p]=c,i&&i!==g&&c&&c===n&&(g.leaveGuards.size||(g.leaveGuards=i.leaveGuards),g.updateGuards.size||(g.updateGuards=i.updateGuards))),c&&g&&(!i||!_o(g,i)||!n)&&(g.enterCallbacks[p]||[]).forEach(h=>h(c))},{flush:"post"}),()=>{const c=x.value,g=r.name,p=u.value,n=p&&p.components[g];if(!n)return Mc(w.default,{Component:n,route:c});const i=p.props[g],a=i?i===!0?c.params:typeof i=="function"?i(c):i:null,y=tr(n,xt({},a,d,{onVnodeUnmounted:l=>{l.component.isUnmounted&&(p.instances[g]=null)},ref:o}));return Mc(w.default,{Component:y,route:c})||y}}});function Mc(r,d){if(!r)return null;const w=r(d);return w.length===1?w[0]:w}const Kf=Fv;function Nv(r){const d=Ev(r.routes,r),w=r.parseQuery||Cv,t=r.stringifyQuery||xc,x=r.history,v=Do(),s=Do(),u=Do(),o=Zo(Zr);let c=Zr;io&&r.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const g=qi.bind(null,$=>""+$),p=qi.bind(null,K0),n=qi.bind(null,rs);function i($,J){let ne,ce;return Yf($)?(ne=d.getRecordMatcher($),ce=J):ce=$,d.addRoute(ce,ne)}function a($){const J=d.getRecordMatcher($);J&&d.removeRoute(J)}function h(){return d.getRoutes().map($=>$.record)}function y($){return!!d.getRecordMatcher($)}function l($,J){if(J=xt({},J||o.value),typeof $=="string"){const z=Xi(w,$,J.path),te=d.resolve({path:z.path},J),le=x.createHref(z.fullPath);return xt(z,te,{params:n(te.params),hash:rs(z.hash),redirectedFrom:void 0,href:le})}let ne;if($.path!=null)ne=xt({},$,{path:Xi(w,$.path,J.path).path});else{const z=xt({},$.params);for(const te in z)z[te]==null&&delete z[te];ne=xt({},$,{params:p(z)}),J.params=p(J.params)}const ce=d.resolve(ne,J),ie=$.hash||"";ce.params=g(n(ce.params));const pe=ev(t,xt({},$,{hash:Y0(ie),path:ce.path})),Z=x.createHref(pe);return xt({fullPath:pe,hash:ie,query:t===xc?Ov($.query):$.query||{}},ce,{redirectedFrom:void 0,href:Z})}function f($){return typeof $=="string"?Xi(w,$,o.value.path):xt({},$)}function m($,J){if(c!==$)return wo(8,{from:J,to:$})}function b($){return E($)}function j($){return b(xt(f($),{replace:!0}))}function M($){const J=$.matched[$.matched.length-1];if(J&&J.redirect){const{redirect:ne}=J;let ce=typeof ne=="function"?ne($):ne;return typeof ce=="string"&&(ce=ce.includes("?")||ce.includes("#")?ce=f(ce):{path:ce},ce.params={}),xt({query:$.query,hash:$.hash,params:ce.path!=null?{}:$.params},ce)}}function E($,J){const ne=c=l($),ce=o.value,ie=$.state,pe=$.force,Z=$.replace===!0,z=M(ne);if(z)return E(xt(f(z),{state:typeof z=="object"?xt({},ie,z.state):ie,force:pe,replace:Z}),J||ne);const te=ne;te.redirectedFrom=J;let le;return!pe&&tv(t,ce,ne)&&(le=wo(16,{to:te,from:ce}),ee(ce,ce,!0,!1)),(le?Promise.resolve(le):L(te,ce)).catch(me=>fn(me)?fn(me,2)?me:K(me):V(me,te,ce)).then(me=>{if(me){if(fn(me,2))return E(xt({replace:Z},f(me.to),{state:typeof me.to=="object"?xt({},ie,me.to.state):ie,force:pe}),J||te)}else me=I(te,ce,!0,Z,ie);return C(te,ce,me),me})}function k($,J){const ne=m($,J);return ne?Promise.reject(ne):Promise.resolve()}function P($){const J=D.values().next().value;return J&&typeof J.runWithContext=="function"?J.runWithContext($):$()}function L($,J){let ne;const[ce,ie,pe]=Uv($,J);ne=Yi(ce.reverse(),"beforeRouteLeave",$,J);for(const z of ce)z.leaveGuards.forEach(te=>{ne.push(On(te,$,J))});const Z=k.bind(null,$,J);return ne.push(Z),W(ne).then(()=>{ne=[];for(const z of v.list())ne.push(On(z,$,J));return ne.push(Z),W(ne)}).then(()=>{ne=Yi(ie,"beforeRouteUpdate",$,J);for(const z of ie)z.updateGuards.forEach(te=>{ne.push(On(te,$,J))});return ne.push(Z),W(ne)}).then(()=>{ne=[];for(const z of pe)if(z.beforeEnter)if(Jr(z.beforeEnter))for(const te of z.beforeEnter)ne.push(On(te,$,J));else ne.push(On(z.beforeEnter,$,J));return ne.push(Z),W(ne)}).then(()=>($.matched.forEach(z=>z.enterCallbacks={}),ne=Yi(pe,"beforeRouteEnter",$,J,P),ne.push(Z),W(ne))).then(()=>{ne=[];for(const z of s.list())ne.push(On(z,$,J));return ne.push(Z),W(ne)}).catch(z=>fn(z,8)?z:Promise.reject(z))}function C($,J,ne){u.list().forEach(ce=>P(()=>ce($,J,ne)))}function I($,J,ne,ce,ie){const pe=m($,J);if(pe)return pe;const Z=J===Zr,z=io?history.state:{};ne&&(ce||Z?x.replace($.fullPath,xt({scroll:Z&&z&&z.scroll},ie)):x.push($.fullPath,ie)),o.value=$,ee($,J,ne,Z),K()}let A;function N(){A||(A=x.listen(($,J,ne)=>{if(!G.listening)return;const ce=l($),ie=M(ce);if(ie){E(xt(ie,{replace:!0}),ce).catch(qo);return}c=ce;const pe=o.value;io&&uv(pc(pe.fullPath,ne.delta),gi()),L(ce,pe).catch(Z=>fn(Z,12)?Z:fn(Z,2)?(E(Z.to,ce).then(z=>{fn(z,20)&&!ne.delta&&ne.type===ns.pop&&x.go(-1,!1)}).catch(qo),Promise.reject()):(ne.delta&&x.go(-ne.delta,!1),V(Z,ce,pe))).then(Z=>{Z=Z||I(ce,pe,!1),Z&&(ne.delta&&!fn(Z,8)?x.go(-ne.delta,!1):ne.type===ns.pop&&fn(Z,20)&&x.go(-1,!1)),C(ce,pe,Z)}).catch(qo)}))}let F=Do(),B=Do(),q;function V($,J,ne){K($);const ce=B.list();return ce.length?ce.forEach(ie=>ie($,J,ne)):console.error($),Promise.reject($)}function H(){return q&&o.value!==Zr?Promise.resolve():new Promise(($,J)=>{F.add([$,J])})}function K($){return q||(q=!$,N(),F.list().forEach(([J,ne])=>$?ne($):J()),F.reset()),$}function ee($,J,ne,ce){const{scrollBehavior:ie}=r;if(!io||!ie)return Promise.resolve();const pe=!ne&&cv(pc($.fullPath,0))||(ce||!ne)&&history.state&&history.state.scroll||null;return Ur().then(()=>ie($,J,pe)).then(Z=>Z&&lv(Z)).catch(Z=>V(Z,$,J))}const ue=$=>x.go($);let T;const D=new Set,G={currentRoute:o,listening:!0,addRoute:i,removeRoute:a,hasRoute:y,getRoutes:h,resolve:l,options:r,push:b,replace:j,go:ue,back:()=>ue(-1),forward:()=>ue(1),beforeEach:v.add,beforeResolve:s.add,afterEach:u.add,onError:B.add,isReady:H,install($){const J=this;$.component("RouterLink",Lv),$.component("RouterView",Kf),$.config.globalProperties.$router=J,Object.defineProperty($.config.globalProperties,"$route",{enumerable:!0,get:()=>Bt(o)}),io&&!T&&o.value===Zr&&(T=!0,b(x.location).catch(ie=>{}));const ne={};for(const ie in Zr)Object.defineProperty(ne,ie,{get:()=>o.value[ie],enumerable:!0});$.provide(yl,J),$.provide(gl,is(ne)),$.provide(La,o);const ce=$.unmount;D.add($),$.unmount=function(){D.delete($),D.size<1&&(c=Zr,A&&A(),A=null,o.value=Zr,T=!1,q=!1),ce()}}};function W($){return $.reduce((J,ne)=>J.then(()=>P(ne)),Promise.resolve())}return G}function Uv(r,d){const w=[],t=[],x=[],v=Math.max(d.matched.length,r.matched.length);for(let s=0;s_o(c,u))?t.push(u):w.push(u));const o=r.matched[s];o&&(d.matched.find(c=>_o(c,o))||x.push(o))}return[w,t,x]}function Bv(){return Ht(gl)}const Gv=(r,d)=>d.path.replace(/(:\w+)\([^)]+\)/g,"$1").replace(/(:\w+)[?+*]/g,"$1").replace(/:\w+/g,w=>{var t;return((t=r.params[w.slice(1)])==null?void 0:t.toString())||""}),Ia=(r,d)=>{const w=r.route.matched.find(x=>{var v;return((v=x.components)==null?void 0:v.default)===r.Component.type}),t=d??(w==null?void 0:w.meta.key)??(w&&Gv(r.route,w));return typeof t=="function"?t(r.route):t},Vv=(r,d)=>({default:()=>r?tr(qp,r===!0?{}:r,d):d});function vl(r){return Array.isArray(r)?r:[r]}const $i=null,Zi=null,wr={layout:"empty"},Ki=null,Qi=null,Ji=null,xr={layout:"light"},jr={layout:"light"},Sr={layout:"light"},ea=null,Er={layout:"light"},Tr={layout:"light"},Mr={layout:"light"},kr={layout:"light"},Cr={layout:"light"},Or={layout:"light"},Pr={layout:"light"},Ar={layout:"light"},ta=null,kc=[{name:"articles-slug",path:"/articles/:slug(.*)*",meta:{},alias:[],redirect:$i==null?void 0:$i.redirect,component:()=>rt(()=>import("./g5yxyt4Q.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8]),import.meta.url).then(r=>r.default||r)},{name:"articles",path:"/articles",meta:{},alias:[],redirect:Zi==null?void 0:Zi.redirect,component:()=>rt(()=>import("./IzO1sTXP.js"),__vite__mapDeps([9,1,2,3,4,5,6,7]),import.meta.url).then(r=>r.default||r)},{name:(wr==null?void 0:wr.name)??"card",path:(wr==null?void 0:wr.path)??"/card",meta:wr||{},alias:(wr==null?void 0:wr.alias)||[],redirect:wr==null?void 0:wr.redirect,component:()=>rt(()=>import("./D24cNfD5.js"),[],import.meta.url).then(r=>r.default||r)},{name:"examples-nested_transitions",path:"/examples/nested_transitions",meta:{},alias:[],redirect:Ki==null?void 0:Ki.redirect,component:()=>rt(()=>import("./CYevVL6b.js"),[],import.meta.url).then(r=>r.default||r)},{name:"index",path:"/",meta:{},alias:[],redirect:Qi==null?void 0:Qi.redirect,component:()=>rt(()=>import("./BPNqVqzl.js"),__vite__mapDeps([10,11,7,4,3]),import.meta.url).then(r=>r.default||r)},{name:"playground-audio",path:"/playground/audio",meta:{},alias:[],redirect:Ji==null?void 0:Ji.redirect,component:()=>rt(()=>import("./CXWT5P23.js"),[],import.meta.url).then(r=>r.default||r)},{name:(xr==null?void 0:xr.name)??"playground-chords",path:(xr==null?void 0:xr.path)??"/playground/chords",meta:xr||{},alias:(xr==null?void 0:xr.alias)||[],redirect:xr==null?void 0:xr.redirect,component:()=>rt(()=>import("./CwlYhM_w.js"),[],import.meta.url).then(r=>r.default||r)},{name:(jr==null?void 0:jr.name)??"playground-conway",path:(jr==null?void 0:jr.path)??"/playground/conway",meta:jr||{},alias:(jr==null?void 0:jr.alias)||[],redirect:jr==null?void 0:jr.redirect,component:()=>rt(()=>import("./CHuhJ_Er.js"),[],import.meta.url).then(r=>r.default||r)},{name:(Sr==null?void 0:Sr.name)??"playground-french",path:(Sr==null?void 0:Sr.path)??"/playground/french",meta:Sr||{},alias:(Sr==null?void 0:Sr.alias)||[],redirect:Sr==null?void 0:Sr.redirect,component:()=>rt(()=>import("./OorYyVAq.js"),__vite__mapDeps([12,4,6]),import.meta.url).then(r=>r.default||r)},{name:"playground",path:"/playground",meta:{},alias:[],redirect:ea==null?void 0:ea.redirect,component:()=>rt(()=>import("./DOZLo8mA.js"),__vite__mapDeps([13,11]),import.meta.url).then(r=>r.default||r)},{name:(Er==null?void 0:Er.name)??"playground-matrix",path:(Er==null?void 0:Er.path)??"/playground/matrix",meta:Er||{},alias:(Er==null?void 0:Er.alias)||[],redirect:Er==null?void 0:Er.redirect,component:()=>rt(()=>import("./BGlOumKY.js"),[],import.meta.url).then(r=>r.default||r)},{name:(Tr==null?void 0:Tr.name)??"playground-metronome",path:(Tr==null?void 0:Tr.path)??"/playground/metronome",meta:Tr||{},alias:(Tr==null?void 0:Tr.alias)||[],redirect:Tr==null?void 0:Tr.redirect,component:()=>rt(()=>import("./wDya3lie.js"),[],import.meta.url).then(r=>r.default||r)},{name:(Mr==null?void 0:Mr.name)??"playground-midi",path:(Mr==null?void 0:Mr.path)??"/playground/midi",meta:Mr||{},alias:(Mr==null?void 0:Mr.alias)||[],redirect:Mr==null?void 0:Mr.redirect,component:()=>rt(()=>import("./DCZXcdSM.js"),[],import.meta.url).then(r=>r.default||r)},{name:(kr==null?void 0:kr.name)??"playground-palettes-mountains",path:(kr==null?void 0:kr.path)??"/playground/palettes/mountains",meta:kr||{},alias:(kr==null?void 0:kr.alias)||[],redirect:kr==null?void 0:kr.redirect,component:()=>rt(()=>import("./BT8WlydD.js"),[],import.meta.url).then(r=>r.default||r)},{name:(Cr==null?void 0:Cr.name)??"playground-palettes-variance",path:(Cr==null?void 0:Cr.path)??"/playground/palettes/variance",meta:Cr||{},alias:(Cr==null?void 0:Cr.alias)||[],redirect:Cr==null?void 0:Cr.redirect,component:()=>rt(()=>import("./B44J2786.js"),[],import.meta.url).then(r=>r.default||r)},{name:(Or==null?void 0:Or.name)??"playground-plotter",path:(Or==null?void 0:Or.path)??"/playground/plotter",meta:Or||{},alias:(Or==null?void 0:Or.alias)||[],redirect:Or==null?void 0:Or.redirect,component:()=>rt(()=>import("./Dw08bDjX.js"),[],import.meta.url).then(r=>r.default||r)},{name:(Pr==null?void 0:Pr.name)??"playground-tiling",path:(Pr==null?void 0:Pr.path)??"/playground/tiling",meta:Pr||{},alias:(Pr==null?void 0:Pr.alias)||[],redirect:Pr==null?void 0:Pr.redirect,component:()=>rt(()=>import("./CiJ7X6_i.js"),[],import.meta.url).then(r=>r.default||r)},{name:(Ar==null?void 0:Ar.name)??"playground-waves",path:(Ar==null?void 0:Ar.path)??"/playground/waves",meta:Ar||{},alias:(Ar==null?void 0:Ar.alias)||[],redirect:Ar==null?void 0:Ar.redirect,component:()=>rt(()=>import("./Bf0jujID.js"),[],import.meta.url).then(r=>r.default||r)},{name:"talks",path:"/talks",meta:{},alias:[],redirect:ta==null?void 0:ta.redirect,component:()=>rt(()=>import("./BqhY8_CC.js"),[],import.meta.url).then(r=>r.default||r)}],Qf=(r,d,w)=>(d=d===!0?{}:d,{default:()=>{var t;return d?tr(r,d,w):(t=w.default)==null?void 0:t.call(w)}});function Cc(r){const d=(r==null?void 0:r.meta.key)??r.path.replace(/(:\w+)\([^)]+\)/g,"$1").replace(/(:\w+)[?+*]/g,"$1").replace(/:\w+/g,w=>{var t;return((t=r.params[w.slice(1)])==null?void 0:t.toString())||""});return typeof d=="function"?d(r):d}function Hv(r,d){return r===d||d===Zr?!1:Cc(r)!==Cc(d)?!0:!r.matched.every((t,x)=>{var v,s;return t.components&&t.components.default===((s=(v=d.matched[x])==null?void 0:v.components)==null?void 0:s.default)})}const zv={scrollBehavior(r,d,w){var c;const t=It(),x=((c=qr().options)==null?void 0:c.scrollBehaviorType)??"auto";let v=w||void 0;const s=typeof r.meta.scrollToTop=="function"?r.meta.scrollToTop(r,d):r.meta.scrollToTop;if(!v&&d&&r&&s!==!1&&Hv(r,d)&&(v={left:0,top:0}),r.path===d.path)return d.hash&&!r.hash?{left:0,top:0}:r.hash?{el:r.hash,top:Oc(r.hash),behavior:x}:!1;const u=g=>!!(g.meta.pageTransition??Pa),o=u(d)&&u(r)?"page:transition:finish":"page:finish";return new Promise(g=>{t.hooks.hookOnce(o,async()=>{await new Promise(p=>setTimeout(p,0)),r.hash&&(v={el:r.hash,top:Oc(r.hash),behavior:x}),g(v)})})}};function Oc(r){try{const d=document.querySelector(r);if(d)return parseFloat(getComputedStyle(d).scrollMarginTop)}catch{}return 0}const Wv={hashMode:!1,scrollBehaviorType:"auto"},Rr={...Wv,...zv},qv=async r=>{var o;let d,w;if(!((o=r.meta)!=null&&o.validate))return;const t=It(),x=qr();if(([d,w]=ts(()=>Promise.resolve(r.meta.validate(r))),d=await d,w(),d)===!0)return;const s=mi({statusCode:404,statusMessage:`Page Not Found: ${r.fullPath}`,data:{path:r.fullPath}}),u=x.beforeResolve(c=>{if(u(),c===r){const g=x.afterEach(async()=>{g(),await t.runWithContext(()=>ao(s)),window.history.pushState({},"",r.fullPath)});return!1}})},Xv=async r=>{let d,w;const t=([d,w]=ts(()=>pl(r.path)),d=await d,w(),d);if(t.redirect)return yn(t.redirect,{acceptRelative:!0})?(window.location.href=t.redirect,!1):t.redirect},Yv=[qv,Xv],Yo={};function $v(r,d,w){const{pathname:t,search:x,hash:v}=d,s=r.indexOf("#");if(s>-1){const c=v.includes(r.slice(s))?r.slice(s).length:1;let g=v.slice(c);return g[0]!=="/"&&(g="/"+g),Zu(g,"")}const u=Zu(t,r),o=!w||Ly(u,w,{trailingSlash:!0})?u:w;return o+(o.includes("?")?"":x)+v}const Zv=gn({name:"nuxt:router",enforce:"pre",async setup(r){var y,l;let d,w,t=fi().app.baseURL;Rr.hashMode&&!t.includes("#")&&(t+="#");const x=((y=Rr.history)==null?void 0:y.call(Rr,t))??(Rr.hashMode?pv(t):Xf(t)),v=((l=Rr.routes)==null?void 0:l.call(Rr,kc))??kc;let s;const u=Nv({...Rr,scrollBehavior:(f,m,b)=>{if(m===Zr){s=b;return}if(Rr.scrollBehavior){if(u.options.scrollBehavior=Rr.scrollBehavior,"scrollRestoration"in window.history){const j=u.beforeEach(()=>{j(),window.history.scrollRestoration="manual"})}return Rr.scrollBehavior(f,Zr,s||b)}},history:x,routes:v});"scrollRestoration"in window.history&&(window.history.scrollRestoration="auto"),r.vueApp.use(u);const o=Zo(u.currentRoute.value);u.afterEach((f,m)=>{o.value=m}),Object.defineProperty(r.vueApp.config.globalProperties,"previousRoute",{get:()=>o.value});const c=$v(t,window.location,r.payload.path),g=Zo(u.currentRoute.value),p=()=>{g.value=u.currentRoute.value};r.hook("page:finish",p),u.afterEach((f,m)=>{var b,j,M,E;((j=(b=f.matched[0])==null?void 0:b.components)==null?void 0:j.default)===((E=(M=m.matched[0])==null?void 0:M.components)==null?void 0:E.default)&&p()});const n={};for(const f in g.value)Object.defineProperty(n,f,{get:()=>g.value[f]});r._route=is(n),r._middleware=r._middleware||{global:[],named:{}};try{[d,w]=ts(()=>u.isReady()),await d,w()}catch(f){[d,w]=ts(()=>r.runWithContext(()=>ao(f))),await d,w()}const i=c!==u.currentRoute.value.fullPath?u.resolve(c):u.currentRoute.value;p();const a=r.payload.state._layout;u.beforeEach(async(f,m)=>{var b;await r.callHook("page:loading:start"),f.meta=Un(f.meta),r.isHydrating&&a&&!yo(f.meta.layout)&&(f.meta.layout=a),r._processingMiddleware=!0;{const j=new Set([...Yv,...r._middleware.global]);for(const M of f.matched){const E=M.meta.middleware;if(E)for(const k of vl(E))j.add(k)}{const M=await r.runWithContext(()=>pl(f.path));if(M.appMiddleware)for(const E in M.appMiddleware)M.appMiddleware[E]?j.add(E):j.delete(E)}for(const M of j){const E=typeof M=="string"?r._middleware.named[M]||await((b=Yo[M])==null?void 0:b.call(Yo).then(P=>P.default||P)):M;if(!E)throw new Error(`Unknown route middleware: '${M}'.`);const k=await r.runWithContext(()=>E(f,m));if(!r.payload.serverRendered&&r.isHydrating&&(k===!1||k instanceof Error)){const P=k||Ta({statusCode:404,statusMessage:`Page Not Found: ${c}`});return await r.runWithContext(()=>ao(P)),!1}if(k!==!0&&(k||k===!1))return k}}}),u.onError(async()=>{delete r._processingMiddleware,await r.callHook("page:loading:end")});const h=pi();return u.afterEach(async(f,m,b)=>{delete r._processingMiddleware,!r.isHydrating&&h.value&&await r.runWithContext(Eg),b&&await r.callHook("page:loading:end"),f.matched.length===0&&await r.runWithContext(()=>ao(Ta({statusCode:404,fatal:!1,statusMessage:`Page not found: ${f.fullPath}`,data:{path:f.fullPath}})))}),r.hooks.hookOnce("app:created",async()=>{try{"name"in i&&(i.name=void 0),await u.replace({...i,force:!0}),u.options.scrollBehavior=Rr.scrollBehavior}catch(f){await r.runWithContext(()=>ao(f))}}),{provide:{router:u}}}}),Da=globalThis.requestIdleCallback||(r=>{const d=Date.now(),w={didTimeout:!1,timeRemaining:()=>Math.max(0,50-(Date.now()-d))};return setTimeout(()=>{r(w)},1)}),Kv=globalThis.cancelIdleCallback||(r=>{clearTimeout(r)}),bl=r=>{const d=It();d.isHydrating?d.hooks.hookOnce("app:suspense:resolve",()=>{Da(r)}):Da(r)},Qv=gn({name:"nuxt:payload",setup(r){qr().beforeResolve(async(d,w)=>{if(d.path===w.path)return;const t=await cc(d.path);t&&Object.assign(r.static.data,t.data)}),bl(()=>{var d;r.hooks.hook("link:prefetch",async w=>{hs(w).protocol||await cc(w)}),((d=navigator.connection)==null?void 0:d.effectiveType)!=="slow-2g"&&setTimeout(yi,1e3)})}}),Jv=gn(r=>{let d;async function w(){const t=await yi();d&&clearTimeout(d),d=setTimeout(w,1e3*60*60);try{const x=await $fetch(cl("builds/latest.json")+`?${Date.now()}`);x.id!==t.id&&r.hooks.callHook("app:manifest:update",x)}catch{}}bl(()=>{d=setTimeout(w,1e3*60*60)})}),eb=ht(()=>rt(()=>import("./v3tOoUxe.js"),__vite__mapDeps([14,5,1,2,3,4,15,6,7]),import.meta.url).then(r=>r.default||r.default||r)),tb=ht(()=>rt(()=>import("./CS4CKjMH.js"),__vite__mapDeps([16,15,6,7,4,3]),import.meta.url).then(r=>r.default||r.default||r)),rb=ht(()=>rt(()=>import("./DjOkkdqj.js"),__vite__mapDeps([17,6,4,7,3]),import.meta.url).then(r=>r.default||r.default||r)),nb=ht(()=>rt(()=>import("./DsRHAFuR.js"),__vite__mapDeps([15,6,7,4,3]),import.meta.url).then(r=>r.default||r.default||r)),ob=ht(()=>rt(()=>import("./mDMTOJLw.js"),__vite__mapDeps([5,1,2,3,4]),import.meta.url).then(r=>r.default||r.default||r)),sb=ht(()=>rt(()=>import("./uYek0qF_.js"),__vite__mapDeps([18,1,2,3,4]),import.meta.url).then(r=>r.default||r.default||r)),ib=ht(()=>rt(()=>import("./-GjkDpfn.js"),[],import.meta.url).then(r=>r.default||r.default||r)),ab=ht(()=>rt(()=>import("./Des7KGkR.js"),[],import.meta.url).then(r=>r.default||r.default||r)),lb=ht(()=>rt(()=>import("./BRI1TGcF.js"),[],import.meta.url).then(r=>r.default||r.default||r)),ub=ht(()=>rt(()=>import("./pTPauEmS.js"),__vite__mapDeps([19,20]),import.meta.url).then(r=>r.default||r.default||r)),cb=ht(()=>rt(()=>import("./D-xzt0Hk.js"),__vite__mapDeps([21,22,23]),import.meta.url).then(r=>r.default||r.default||r)),db=ht(()=>rt(()=>import("./pMxOCLTg.js"),[],import.meta.url).then(r=>r.default||r.default||r)),fb=ht(()=>rt(()=>import("./DltOabO9.js"),__vite__mapDeps([24,22,23]),import.meta.url).then(r=>r.default||r.default||r)),hb=ht(()=>rt(()=>import("./DcLi_FTb.js"),[],import.meta.url).then(r=>r.default||r.default||r)),pb=ht(()=>rt(()=>import("./Dyf09I7x.js"),[],import.meta.url).then(r=>r.default||r.default||r)),mb=ht(()=>rt(()=>import("./v_KFgWUo.js"),[],import.meta.url).then(r=>r.default||r.default||r)),yb=ht(()=>rt(()=>import("./DP6TDZ8u.js"),[],import.meta.url).then(r=>r.default||r.default||r)),gb=ht(()=>rt(()=>import("./CxWdTzCB.js"),[],import.meta.url).then(r=>r.default||r.default||r)),vb=ht(()=>rt(()=>import("./BSSPlG-l.js"),[],import.meta.url).then(r=>r.default||r.default||r)),bb=ht(()=>rt(()=>import("./C67JdZ9D.js"),[],import.meta.url).then(r=>r.default||r.default||r)),_b=ht(()=>rt(()=>import("./C-6Jpe-m.js"),[],import.meta.url).then(r=>r.default||r.default||r)),wb=ht(()=>rt(()=>import("./Iio6RtF1.js"),[],import.meta.url).then(r=>r.default||r.default||r)),xb=ht(()=>rt(()=>import("./CAu-wKXH.js"),[],import.meta.url).then(r=>r.default||r.default||r)),jb=ht(()=>rt(()=>import("./4KDx6Qdh.js"),[],import.meta.url).then(r=>r.default||r.default||r)),Sb=ht(()=>rt(()=>import("./TE8sWSFL.js"),[],import.meta.url).then(r=>r.default||r.default||r)),Eb=ht(()=>rt(()=>import("./N3o-VwNZ.js"),[],import.meta.url).then(r=>r.default||r.default||r)),Tb=ht(()=>rt(()=>import("./SY0NXAMn.js"),[],import.meta.url).then(r=>r.default||r.default||r)),Mb=ht(()=>rt(()=>import("./CfFW-P5d.js"),[],import.meta.url).then(r=>r.default||r.default||r)),kb=ht(()=>rt(()=>import("./BnxxK6MW.js"),[],import.meta.url).then(r=>r.default||r.default||r)),Cb=ht(()=>rt(()=>import("./BN984TM9.js"),[],import.meta.url).then(r=>r.default||r.default||r)),Ob=ht(()=>rt(()=>import("./DJOb4bXW.js"),[],import.meta.url).then(r=>r.default||r.default||r)),Pb=ht(()=>rt(()=>import("./BwySm3O-.js"),[],import.meta.url).then(r=>r.default||r.default||r)),Ab=ht(()=>rt(()=>import("./ClOZFDRl.js"),[],import.meta.url).then(r=>r.default||r.default||r)),Rb=ht(()=>rt(()=>import("./B8Io8PDA.js"),[],import.meta.url).then(r=>r.default||r.default||r)),Lb=ht(()=>rt(()=>import("./4ZR8vDGy.js"),[],import.meta.url).then(r=>r.default||r.default||r)),Ib=ht(()=>rt(()=>import("./BPDZZsV6.js"),[],import.meta.url).then(r=>r.default||r.default||r)),Db=[["ContentDoc",eb],["ContentList",tb],["ContentNavigation",rb],["ContentQuery",nb],["ContentRenderer",ob],["ContentRendererMarkdown",sb],["MDCSlot",ib],["DocumentDrivenEmpty",ab],["DocumentDrivenNotFound",lb],["Markdown",ub],["ProseCode",cb],["ProseCodeInline",db],["ProsePre",fb],["ProseA",hb],["ProseBlockquote",pb],["ProseEm",mb],["ProseH1",yb],["ProseH2",gb],["ProseH3",vb],["ProseH4",bb],["ProseH5",_b],["ProseH6",wb],["ProseHr",xb],["ProseImg",jb],["ProseLi",Sb],["ProseOl",Eb],["ProseP",Tb],["ProseScript",Mb],["ProseStrong",kb],["ProseTable",Cb],["ProseTbody",Ob],["ProseTd",Pb],["ProseTh",Ab],["ProseThead",Rb],["ProseTr",Lb],["ProseUl",Ib]],Fb=gn({name:"nuxt:global-components",setup(r){for(const[d,w]of Db)r.vueApp.component(d,w),r.vueApp.component("Lazy"+d,w)}}),Pn={default:()=>rt(()=>import("./CM0LhmwP.js"),[],import.meta.url).then(r=>r.default||r),empty:()=>rt(()=>import("./DbroGl9h.js"),[],import.meta.url).then(r=>r.default||r),light:()=>rt(()=>import("./DsILVI33.js"),[],import.meta.url).then(r=>r.default||r)},Nb=gn({name:"nuxt:prefetch",setup(r){const d=qr();r.hooks.hook("app:mounted",()=>{d.beforeEach(async w=>{var x;const t=(x=w==null?void 0:w.meta)==null?void 0:x.layout;t&&typeof Pn[t]=="function"&&await Pn[t]()})}),r.hooks.hook("link:prefetch",w=>{if(yn(w))return;const t=d.resolve(w);if(!t)return;const x=t.meta.layout;let v=vl(t.meta.middleware);v=v.filter(s=>typeof s=="string");for(const s of v)typeof Yo[s]=="function"&&Yo[s]();x&&typeof Pn[x]=="function"&&Pn[x]()})}});function Ub(r={}){const d=r.path||window.location.pathname;let w={};try{w=$s(sessionStorage.getItem("nuxt:reload")||"{}")}catch{}if(r.force||(w==null?void 0:w.path)!==d||(w==null?void 0:w.expires){t.clear()}),r.hook("app:chunkError",({error:v})=>{t.add(v)});function x(v){const u="href"in v&&v.href[0]==="#"?w.app.baseURL+v.href:di(w.app.baseURL,v.fullPath);Ub({path:u,persistState:!0})}r.hook("app:manifest:update",()=>{d.beforeResolve(x)}),d.onError((v,s)=>{t.has(v)&&x(s)})}});var As=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function Gb(r){return r&&r.__esModule&&Object.prototype.hasOwnProperty.call(r,"default")?r.default:r}function Rs(r){throw new Error('Could not dynamically require "'+r+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var Jf={exports:{}};/*! p5.js v1.9.3 April 24, 2024 */(function(r,d){(function(w){r.exports=w()})(function(){var w;return function t(x,v,s){function u(g,p){if(!v[g]){if(!x[g]){var n=typeof Rs=="function"&&Rs;if(!p&&n)return n(g,!0);if(o)return o(g,!0);throw(p=new Error("Cannot find module '"+g+"'")).code="MODULE_NOT_FOUND",p}n=v[g]={exports:{}},x[g][0].call(n.exports,function(i){return u(x[g][1][i]||i)},n,n.exports,t,x,v,s)}return v[g].exports}for(var o=typeof Rs=="function"&&Rs,c=0;c>16&255,f[m++]=a>>8&255,f[m++]=255&a;return l===2&&(a=u[i.charCodeAt(h)]<<2|u[i.charCodeAt(h+1)]>>4,f[m++]=255&a),l===1&&(a=u[i.charCodeAt(h)]<<10|u[i.charCodeAt(h+1)]<<4|u[i.charCodeAt(h+2)]>>2,f[m++]=a>>8&255,f[m++]=255&a),f},v.fromByteArray=function(i){for(var a,h=i.length,y=h%3,l=[],f=0,m=h-y;f>18&63]+s[L>>12&63]+s[L>>6&63]+s[63&L]}(E));return k.join("")}(i,f,m>2]+s[a<<4&63]+"==")):y==2&&(a=(i[h-2]<<8)+i[h-1],l.push(s[a>>10]+s[a>>4&63]+s[a<<2&63]+"=")),l.join("")};for(var s=[],u=[],o=typeof Uint8Array<"u"?Uint8Array:Array,c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",g=0,p=c.length;g>>1;case"base64":return V(T).length;default:if($)return W?-1:q(T).length;D=(""+D).toLowerCase(),$=!0}}function m(T,D,G){var W,$=!1;if((D=D===void 0||D<0?0:D)>this.length||(G=G===void 0||G>this.length?this.length:G)<=0||(G>>>=0)<=(D>>>=0))return"";for(T=T||"utf8";;)switch(T){case"hex":var J=this,de=D,ne=G,Z=J.length;(!ne||ne<0||Z=T.length){if($)return-1;G=T.length-1}else if(G<0){if(!$)return-1;G=0}if(typeof D=="string"&&(D=n.from(D,W)),n.isBuffer(D))return D.length===0?-1:M(T,D,G,W,$);if(typeof D=="number")return D&=255,typeof Uint8Array.prototype.indexOf=="function"?($?Uint8Array.prototype.indexOf:Uint8Array.prototype.lastIndexOf).call(T,D,G):M(T,[D],G,W,$);throw new TypeError("val must be string, number or Buffer")}function M(T,D,G,W,$){var J=1,ne=T.length,ce=D.length;if(W!==void 0&&((W=String(W).toLowerCase())==="ucs2"||W==="ucs-2"||W==="utf16le"||W==="utf-16le")){if(T.length<2||D.length<2)return-1;ne/=J=2,ce/=2,G/=2}function ie(le,me){return J===1?le[me]:le.readUInt16BE(me*J)}if($)for(var pe=-1,Z=G;Z>8,ce=ce%256,ie.push(ce),ie.push(ne);return ie}(D,T.length-G),T,G,W)}function P(T,D,G){G=Math.min(T.length,G);for(var W=[],$=D;$>>10&1023|55296),Z=56320|1023&Z),W.push(Z),$+=z}var te=W,le=te.length;if(le<=L)return String.fromCharCode.apply(String,te);for(var me="",de=0;de"u"||typeof console.error!="function"||console.error("This browser lacks typed array (Uint8Array) support which is required by `buffer` v5.x. Use `buffer` v4.x if you require old browser support."),Object.defineProperty(n.prototype,"parent",{enumerable:!0,get:function(){if(n.isBuffer(this))return this.buffer}}),Object.defineProperty(n.prototype,"offset",{enumerable:!0,get:function(){if(n.isBuffer(this))return this.byteOffset}}),typeof Symbol<"u"&&Symbol.species!=null&&n[Symbol.species]===n&&Object.defineProperty(n,Symbol.species,{value:null,configurable:!0,enumerable:!1,writable:!1}),n.poolSize=8192,n.from=i,Object.setPrototypeOf(n.prototype,Uint8Array.prototype),Object.setPrototypeOf(n,Uint8Array),n.alloc=function(T,D,G){return D=D,G=G,a(T=T),!(T<=0)&&D!==void 0?typeof G=="string"?p(T).fill(D,G):p(T).fill(D):p(T)},n.allocUnsafe=h,n.allocUnsafeSlow=h,n.isBuffer=function(T){return T!=null&&T._isBuffer===!0&&T!==n.prototype},n.compare=function(T,D){if(K(T,Uint8Array)&&(T=n.from(T,T.offset,T.byteLength)),K(D,Uint8Array)&&(D=n.from(D,D.offset,D.byteLength)),!n.isBuffer(T)||!n.isBuffer(D))throw new TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array');if(T===D)return 0;for(var G=T.length,W=D.length,$=0,J=Math.min(G,W);$T&&(D+=" ... "),""},c&&(n.prototype[c]=n.prototype.inspect),n.prototype.compare=function(T,D,G,W,$){if(K(T,Uint8Array)&&(T=n.from(T,T.offset,T.byteLength)),!n.isBuffer(T))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof T);if(G===void 0&&(G=T?T.length:0),W===void 0&&(W=0),$===void 0&&($=this.length),(D=D===void 0?0:D)<0||G>T.length||W<0||$>this.length)throw new RangeError("out of range index");if($<=W&&G<=D)return 0;if($<=W)return-1;if(G<=D)return 1;if(this===T)return 0;for(var J=($>>>=0)-(W>>>=0),ne=(G>>>=0)-(D>>>=0),ce=Math.min(J,ne),ie=this.slice(W,$),pe=T.slice(D,G),Z=0;Z>>=0,isFinite(G)?(G>>>=0,W===void 0&&(W="utf8")):(W=G,G=void 0)}var $=this.length-D;if((G===void 0||$this.length)throw new RangeError("Attempt to write outside buffer bounds");W=W||"utf8";for(var J,ne,ce,ie=!1;;)switch(W){case"hex":var pe=this,Z=T,z=D,te=G,le=(z=Number(z)||0,pe.length-z);(!te||le<(te=Number(te)))&&(te=le),(le=Z.length)/2T.length)throw new RangeError("Index out of range")}function A(T,D,G,W){if(G+W>T.length)throw new RangeError("Index out of range");if(G<0)throw new RangeError("Index out of range")}function N(T,D,G,W,$){return D=+D,G>>>=0,$||A(T,0,G,4),o.write(T,D,G,W,23,4),G+4}function F(T,D,G,W,$){return D=+D,G>>>=0,$||A(T,0,G,8),o.write(T,D,G,W,52,8),G+8}n.prototype.slice=function(T,D){var G=this.length,G=((T=~~T)<0?(T+=G)<0&&(T=0):G>>=0,D>>>=0,G||C(T,D,this.length);for(var W=this[T],$=1,J=0;++J>>=0,D>>>=0,G||C(T,D,this.length);for(var W=this[T+--D],$=1;0>>=0,D||C(T,1,this.length),this[T]},n.prototype.readUInt16LE=function(T,D){return T>>>=0,D||C(T,2,this.length),this[T]|this[T+1]<<8},n.prototype.readUInt16BE=function(T,D){return T>>>=0,D||C(T,2,this.length),this[T]<<8|this[T+1]},n.prototype.readUInt32LE=function(T,D){return T>>>=0,D||C(T,4,this.length),(this[T]|this[T+1]<<8|this[T+2]<<16)+16777216*this[T+3]},n.prototype.readUInt32BE=function(T,D){return T>>>=0,D||C(T,4,this.length),16777216*this[T]+(this[T+1]<<16|this[T+2]<<8|this[T+3])},n.prototype.readIntLE=function(T,D,G){T>>>=0,D>>>=0,G||C(T,D,this.length);for(var W=this[T],$=1,J=0;++J>>=0,D>>>=0,G||C(T,D,this.length);for(var W=D,$=1,J=this[T+--W];0>>=0,D||C(T,1,this.length),128&this[T]?-1*(255-this[T]+1):this[T]},n.prototype.readInt16LE=function(T,D){return T>>>=0,D||C(T,2,this.length),D=this[T]|this[T+1]<<8,32768&D?4294901760|D:D},n.prototype.readInt16BE=function(T,D){return T>>>=0,D||C(T,2,this.length),D=this[T+1]|this[T]<<8,32768&D?4294901760|D:D},n.prototype.readInt32LE=function(T,D){return T>>>=0,D||C(T,4,this.length),this[T]|this[T+1]<<8|this[T+2]<<16|this[T+3]<<24},n.prototype.readInt32BE=function(T,D){return T>>>=0,D||C(T,4,this.length),this[T]<<24|this[T+1]<<16|this[T+2]<<8|this[T+3]},n.prototype.readFloatLE=function(T,D){return T>>>=0,D||C(T,4,this.length),o.read(this,T,!0,23,4)},n.prototype.readFloatBE=function(T,D){return T>>>=0,D||C(T,4,this.length),o.read(this,T,!1,23,4)},n.prototype.readDoubleLE=function(T,D){return T>>>=0,D||C(T,8,this.length),o.read(this,T,!0,52,8)},n.prototype.readDoubleBE=function(T,D){return T>>>=0,D||C(T,8,this.length),o.read(this,T,!1,52,8)},n.prototype.writeUIntLE=function(T,D,G,W){T=+T,D>>>=0,G>>>=0,W||I(this,T,D,G,Math.pow(2,8*G)-1,0);var $=1,J=0;for(this[D]=255&T;++J>>=0,G>>>=0,W||I(this,T,D,G,Math.pow(2,8*G)-1,0);var $=G-1,J=1;for(this[D+$]=255&T;0<=--$&&(J*=256);)this[D+$]=T/J&255;return D+G},n.prototype.writeUInt8=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,1,255,0),this[D]=255&T,D+1},n.prototype.writeUInt16LE=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,2,65535,0),this[D]=255&T,this[D+1]=T>>>8,D+2},n.prototype.writeUInt16BE=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,2,65535,0),this[D]=T>>>8,this[D+1]=255&T,D+2},n.prototype.writeUInt32LE=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,4,4294967295,0),this[D+3]=T>>>24,this[D+2]=T>>>16,this[D+1]=T>>>8,this[D]=255&T,D+4},n.prototype.writeUInt32BE=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,4,4294967295,0),this[D]=T>>>24,this[D+1]=T>>>16,this[D+2]=T>>>8,this[D+3]=255&T,D+4},n.prototype.writeIntLE=function(T,D,G,W){T=+T,D>>>=0,W||I(this,T,D,G,(W=Math.pow(2,8*G-1))-1,-W);var $=0,J=1,ne=0;for(this[D]=255&T;++$>0)-ne&255;return D+G},n.prototype.writeIntBE=function(T,D,G,W){T=+T,D>>>=0,W||I(this,T,D,G,(W=Math.pow(2,8*G-1))-1,-W);var $=G-1,J=1,ne=0;for(this[D+$]=255&T;0<=--$&&(J*=256);)T<0&&ne===0&&this[D+$+1]!==0&&(ne=1),this[D+$]=(T/J>>0)-ne&255;return D+G},n.prototype.writeInt8=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,1,127,-128),this[D]=255&(T=T<0?255+T+1:T),D+1},n.prototype.writeInt16LE=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,2,32767,-32768),this[D]=255&T,this[D+1]=T>>>8,D+2},n.prototype.writeInt16BE=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,2,32767,-32768),this[D]=T>>>8,this[D+1]=255&T,D+2},n.prototype.writeInt32LE=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,4,2147483647,-2147483648),this[D]=255&T,this[D+1]=T>>>8,this[D+2]=T>>>16,this[D+3]=T>>>24,D+4},n.prototype.writeInt32BE=function(T,D,G){return T=+T,D>>>=0,G||I(this,T,D,4,2147483647,-2147483648),this[D]=(T=T<0?4294967295+T+1:T)>>>24,this[D+1]=T>>>16,this[D+2]=T>>>8,this[D+3]=255&T,D+4},n.prototype.writeFloatLE=function(T,D,G){return N(this,T,D,!0,G)},n.prototype.writeFloatBE=function(T,D,G){return N(this,T,D,!1,G)},n.prototype.writeDoubleLE=function(T,D,G){return F(this,T,D,!0,G)},n.prototype.writeDoubleBE=function(T,D,G){return F(this,T,D,!1,G)},n.prototype.copy=function(T,D,G,W){if(!n.isBuffer(T))throw new TypeError("argument should be a Buffer");if(G=G||0,W||W===0||(W=this.length),D>=T.length&&(D=T.length),(W=0=this.length)throw new RangeError("Index out of range");if(W<0)throw new RangeError("sourceEnd out of bounds");W>this.length&&(W=this.length);var $=(W=T.length-D>>=0,G=G===void 0?this.length:G>>>0,typeof(T=T||0)=="number")for(J=D;J>6|192,63&G|128)}else if(G<65536){if((D-=3)<0)break;J.push(G>>12|224,G>>6&63|128,63&G|128)}else{if(!(G<1114112))throw new Error("Invalid code point");if((D-=4)<0)break;J.push(G>>18|240,G>>12&63|128,G>>6&63|128,63&G|128)}}return J}function V(T){return u.toByteArray(function(D){if((D=(D=D.split("=")[0]).trim().replace(B,"")).length<2)return"";for(;D.length%4!=0;)D+="=";return D}(T))}function H(T,D,G,W){for(var $=0;$=D.length||$>=T.length);++$)D[$+G]=T[$];return $}function K(T,D){return T instanceof D||T!=null&&T.constructor!=null&&T.constructor.name!=null&&T.constructor.name===D.name}function ee(T){return T!=T}var ue=function(){for(var T="0123456789abcdef",D=new Array(256),G=0;G<16;++G)for(var W=16*G,$=0;$<16;++$)D[W+$]=T[G]+T[$];return D}()}).call(this,t("buffer").Buffer)},{"base64-js":1,buffer:4,ieee754:251}],5:[function(t,x,v){x.exports=function(s){if(typeof s!="function")throw TypeError(String(s)+" is not a function");return s}},{}],6:[function(t,x,v){var s=t("../internals/is-object");x.exports=function(u){if(s(u)||u===null)return u;throw TypeError("Can't set "+String(u)+" as a prototype")}},{"../internals/is-object":75}],7:[function(o,x,v){var s=o("../internals/well-known-symbol"),u=o("../internals/object-create"),o=o("../internals/object-define-property"),c=s("unscopables"),g=Array.prototype;g[c]==null&&o.f(g,c,{configurable:!0,value:u(null)}),x.exports=function(p){g[c][p]=!0}},{"../internals/object-create":91,"../internals/object-define-property":93,"../internals/well-known-symbol":149}],8:[function(t,x,v){var s=t("../internals/string-multibyte").charAt;x.exports=function(u,o,c){return o+(c?s(u,o).length:1)}},{"../internals/string-multibyte":124}],9:[function(t,x,v){x.exports=function(s,u,o){if(s instanceof u)return s;throw TypeError("Incorrect "+(o?o+" ":"")+"invocation")}},{}],10:[function(t,x,v){var s=t("../internals/is-object");x.exports=function(u){if(s(u))return u;throw TypeError(String(u)+" is not an object")}},{"../internals/is-object":75}],11:[function(t,x,v){x.exports=typeof ArrayBuffer<"u"&&typeof DataView<"u"},{}],12:[function(A,x,v){function s(F){return p(F)&&n(N,i(F))}var u,o=A("../internals/array-buffer-native"),c=A("../internals/descriptors"),g=A("../internals/global"),p=A("../internals/is-object"),n=A("../internals/has"),i=A("../internals/classof"),a=A("../internals/create-non-enumerable-property"),h=A("../internals/redefine"),y=A("../internals/object-define-property").f,l=A("../internals/object-get-prototype-of"),f=A("../internals/object-set-prototype-of"),L=A("../internals/well-known-symbol"),A=A("../internals/uid"),m=g.Int8Array,b=m&&m.prototype,j=g.Uint8ClampedArray,j=j&&j.prototype,M=m&&l(m),E=b&&l(b),k=Object.prototype,P=k.isPrototypeOf,L=L("toStringTag"),C=A("TYPED_ARRAY_TAG"),I=o&&!!f&&i(g.opera)!=="Opera",A=!1,N={Int8Array:1,Uint8Array:1,Uint8ClampedArray:1,Int16Array:2,Uint16Array:2,Int32Array:4,Uint32Array:4,Float32Array:4,Float64Array:8};for(u in N)g[u]||(I=!1);if((!I||typeof M!="function"||M===Function.prototype)&&(M=function(){throw TypeError("Incorrect invocation")},I))for(u in N)g[u]&&f(g[u],M);if((!I||!E||E===k)&&(E=M.prototype,I))for(u in N)g[u]&&f(g[u].prototype,E);if(I&&l(j)!==E&&f(j,E),c&&!n(E,L))for(u in A=!0,y(E,L,{get:function(){return p(this)?this[C]:void 0}}),N)g[u]&&a(g[u],C,u);x.exports={NATIVE_ARRAY_BUFFER_VIEWS:I,TYPED_ARRAY_TAG:A&&C,aTypedArray:function(F){if(s(F))return F;throw TypeError("Target is not a typed array")},aTypedArrayConstructor:function(F){if(f){if(P.call(M,F))return F}else for(var B in N)if(n(N,u)&&(B=g[B],B&&(F===B||P.call(B,F))))return F;throw TypeError("Target is not a typed array constructor")},exportTypedArrayMethod:function(F,B,q){if(c){if(q)for(var V in N)V=g[V],V&&n(V.prototype,F)&&delete V.prototype[F];E[F]&&!q||h(E,F,!q&&I&&b[F]||B)}},exportTypedArrayStaticMethod:function(F,B,q){var V,H;if(c){if(f){if(q)for(V in N)(H=g[V])&&n(H,F)&&delete H[F];if(M[F]&&!q)return;try{return h(M,F,!q&&I&&m[F]||B)}catch{}}for(V in N)!(H=g[V])||H[F]&&!q||h(H,F,B)}},isView:function(F){return F=i(F),F==="DataView"||n(N,F)},isTypedArray:s,TypedArray:M,TypedArrayPrototype:E}},{"../internals/array-buffer-native":11,"../internals/classof":29,"../internals/create-non-enumerable-property":38,"../internals/descriptors":43,"../internals/global":60,"../internals/has":61,"../internals/is-object":75,"../internals/object-define-property":93,"../internals/object-get-prototype-of":98,"../internals/object-set-prototype-of":102,"../internals/redefine":109,"../internals/uid":146,"../internals/well-known-symbol":149}],13:[function(G,x,v){function s(z){return[255&z]}function u(z){return[255&z,z>>8&255]}function o(z){return[255&z,z>>8&255,z>>16&255,z>>24&255]}function c(z){return z[3]<<24|z[2]<<16|z[1]<<8|z[0]}function g(z){return J(z,23,4)}function p(z){return J(z,52,8)}function n(z,te){A(z[K],te,{get:function(){return B(this)[te]}})}function i(ge,te,ye,me){if(ye=k(ye),ge=B(ge),ye+te>ge.byteLength)throw $(ee);var de=B(ge.buffer).bytes,ye=ye+ge.byteOffset,ge=de.slice(ye,ye+te);return me?ge:ge.reverse()}function a(z,te,le,me,de,ye){if(le=k(le),z=B(z),le+te>z.byteLength)throw $(ee);for(var ge=B(z.buffer).bytes,Me=le+z.byteOffset,be=me(+de),Ie=0;Iepe;)(ce=ie[pe++])in T||f(T,ce,ue[ce]);h.constructor=T}C&&L(G)!==W&&C(G,W);var P=new D(new T(2)),Z=G.setInt8;P.setInt8(0,2147483648),P.setInt8(1,2147483649),!P.getInt8(0)&&P.getInt8(1)||m(G,{setInt8:function(te,le){Z.call(this,te,le<<24>>24)},setUint8:function(te,le){Z.call(this,te,le<<24>>24)}},{unsafe:!0})}else T=function(z){j(this,T,V),z=k(z),q(this,{bytes:N.call(new Array(z),0),byteLength:z}),y||(this.byteLength=z)},D=function(z,de,le){j(this,D,H),j(z,T,H);var me=B(z).byteLength,de=M(de);if(de<0||me>24},getUint8:function(z){return i(this,1,z)[0]},getInt16:function(z){return z=i(this,2,z,1>16},getUint16:function(z){return z=i(this,2,z,1>>0},getFloat32:function(z){return ne(i(this,4,z,1"+n+""}},{"../internals/require-object-coercible":114}],37:[function(t,x,v){function s(){return this}var u=t("../internals/iterators-core").IteratorPrototype,o=t("../internals/object-create"),c=t("../internals/create-property-descriptor"),g=t("../internals/set-to-string-tag"),p=t("../internals/iterators");x.exports=function(n,i,a){return i+=" Iterator",n.prototype=o(u,{next:c(1,a)}),g(n,i,!1,!0),p[i]=s,n}},{"../internals/create-property-descriptor":39,"../internals/iterators":80,"../internals/iterators-core":79,"../internals/object-create":91,"../internals/set-to-string-tag":118}],38:[function(t,x,v){var s=t("../internals/descriptors"),u=t("../internals/object-define-property"),o=t("../internals/create-property-descriptor");x.exports=s?function(c,g,p){return u.f(c,g,o(1,p))}:function(c,g,p){return c[g]=p,c}},{"../internals/create-property-descriptor":39,"../internals/descriptors":43,"../internals/object-define-property":93}],39:[function(t,x,v){x.exports=function(s,u){return{enumerable:!(1&s),configurable:!(2&s),writable:!(4&s),value:u}}},{}],40:[function(t,x,v){var s=t("../internals/to-primitive"),u=t("../internals/object-define-property"),o=t("../internals/create-property-descriptor");x.exports=function(c,g,p){g=s(g),g in c?u.f(c,g,o(0,p)):c[g]=p}},{"../internals/create-property-descriptor":39,"../internals/object-define-property":93,"../internals/to-primitive":141}],41:[function(l,x,v){function s(){return this}var u=l("../internals/export"),o=l("../internals/create-iterator-constructor"),c=l("../internals/object-get-prototype-of"),g=l("../internals/object-set-prototype-of"),p=l("../internals/set-to-string-tag"),n=l("../internals/create-non-enumerable-property"),i=l("../internals/redefine"),a=l("../internals/well-known-symbol"),h=l("../internals/is-pure"),y=l("../internals/iterators"),l=l("../internals/iterators-core"),f=l.IteratorPrototype,m=l.BUGGY_SAFARI_ITERATORS,b=a("iterator"),j="values",M="entries";x.exports=function(E,k,P,q,C,I,A){o(P,k,q);function N(T){if(T===C&&ee)return ee;if(!m&&T in H)return H[T];switch(T){case"keys":case j:case M:return function(){return new P(this,T)}}return function(){return new P(this)}}var F,B,q=k+" Iterator",V=!1,H=E.prototype,K=H[b]||H["@@iterator"]||C&&H[C],ee=!m&&K||N(C),ue=k=="Array"&&H.entries||K;if(ue&&(ue=c(ue.call(new E)),f!==Object.prototype&&ue.next&&(h||c(ue)===f||(g?g(ue,f):typeof ue[b]!="function"&&n(ue,b,s)),p(ue,q,!0,!0),h&&(y[q]=s))),C==j&&K&&K.name!==j&&(V=!0,ee=function(){return K.call(this)}),h&&!A||H[b]===ee||n(H,b,ee),y[k]=ee,C)if(F={values:N(j),keys:I?ee:N("keys"),entries:N(M)},A)for(B in F)!m&&!V&&B in H||i(H,B,F[B]);else u({target:k,proto:!0,forced:m||V},F);return F}},{"../internals/create-iterator-constructor":37,"../internals/create-non-enumerable-property":38,"../internals/export":50,"../internals/is-pure":76,"../internals/iterators":80,"../internals/iterators-core":79,"../internals/object-get-prototype-of":98,"../internals/object-set-prototype-of":102,"../internals/redefine":109,"../internals/set-to-string-tag":118,"../internals/well-known-symbol":149}],42:[function(t,x,v){var s=t("../internals/path"),u=t("../internals/has"),o=t("../internals/well-known-symbol-wrapped"),c=t("../internals/object-define-property").f;x.exports=function(g){var p=s.Symbol||(s.Symbol={});u(p,g)||c(p,g,{value:o.f(g)})}},{"../internals/has":61,"../internals/object-define-property":93,"../internals/path":105,"../internals/well-known-symbol-wrapped":148}],43:[function(t,x,v){t=t("../internals/fails"),x.exports=!t(function(){return Object.defineProperty({},1,{get:function(){return 7}})[1]!=7})},{"../internals/fails":51}],44:[function(u,x,v){var s=u("../internals/global"),u=u("../internals/is-object"),o=s.document,c=u(o)&&u(o.createElement);x.exports=function(g){return c?o.createElement(g):{}}},{"../internals/global":60,"../internals/is-object":75}],45:[function(t,x,v){x.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},{}],46:[function(t,x,v){t=t("../internals/engine-user-agent"),x.exports=/(iphone|ipod|ipad).*applewebkit/i.test(t)},{"../internals/engine-user-agent":47}],47:[function(t,x,v){t=t("../internals/get-built-in"),x.exports=t("navigator","userAgent")||""},{"../internals/get-built-in":57}],48:[function(o,x,v){var s,u,c=o("../internals/global"),o=o("../internals/engine-user-agent"),c=c.process,c=c&&c.versions,c=c&&c.v8;c?u=(s=c.split("."))[0]+s[1]:o&&(!(s=o.match(/Edge\/(\d+)/))||74<=s[1])&&(s=o.match(/Chrome\/(\d+)/))&&(u=s[1]),x.exports=u&&+u},{"../internals/engine-user-agent":47,"../internals/global":60}],49:[function(t,x,v){x.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},{}],50:[function(t,x,v){var s=t("../internals/global"),u=t("../internals/object-get-own-property-descriptor").f,o=t("../internals/create-non-enumerable-property"),c=t("../internals/redefine"),g=t("../internals/set-global"),p=t("../internals/copy-constructor-properties"),n=t("../internals/is-forced");x.exports=function(i,a){var h,y,l,f=i.target,m=i.global,b=i.stat,j=m?s:b?s[f]||g(f,{}):(s[f]||{}).prototype;if(j)for(h in a){if(y=a[h],l=i.noTargetGet?(l=u(j,h))&&l.value:j[h],!n(m?h:f+(b?".":"#")+h,i.forced)&&l!==void 0){if(typeof y==typeof l)continue;p(y,l)}(i.sham||l&&l.sham)&&o(y,"sham",!0),c(j,h,y,i)}}},{"../internals/copy-constructor-properties":33,"../internals/create-non-enumerable-property":38,"../internals/global":60,"../internals/is-forced":74,"../internals/object-get-own-property-descriptor":94,"../internals/redefine":109,"../internals/set-global":116}],51:[function(t,x,v){x.exports=function(s){try{return!!s()}catch{return!0}}},{}],52:[function(a,x,v){a("../modules/es.regexp.exec");var s=a("../internals/redefine"),u=a("../internals/fails"),o=a("../internals/well-known-symbol"),c=a("../internals/regexp-exec"),g=a("../internals/create-non-enumerable-property"),p=o("species"),n=!u(function(){var l=/./;return l.exec=function(){var f=[];return f.groups={a:"7"},f},"".replace(l,"$")!=="7"}),i="a".replace(/./,"$0")==="$0",a=o("replace"),h=!!/./[a]&&/./[a]("a","$0")==="",y=!u(function(){var f=/(?:)/,l=f.exec,f=(f.exec=function(){return l.apply(this,arguments)},"ab".split(f));return f.length!==2||f[0]!=="a"||f[1]!=="b"});x.exports=function(l,f,m,b){var j,M,E=o(l),k=!u(function(){var L={};return L[E]=function(){return 7},""[l](L)!=7}),P=k&&!u(function(){var L=!1,C=/a/;return l==="split"&&((C={constructor:{}}).constructor[p]=function(){return C},C.flags="",C[E]=/./[E]),C.exec=function(){return L=!0,null},C[E](""),!L});k&&P&&(l!=="replace"||n&&i&&!h)&&(l!=="split"||y)||(j=/./[E],m=(P=m(E,""[l],function(L,C,I,A,N){return C.exec===c?k&&!N?{done:!0,value:j.call(C,I,A)}:{done:!0,value:L.call(I,C,A)}:{done:!1}},{REPLACE_KEEPS_$0:i,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:h}))[0],M=P[1],s(String.prototype,l,m),s(RegExp.prototype,E,f==2?function(L,C){return M.call(L,this,C)}:function(L){return M.call(L,this)})),b&&g(RegExp.prototype[E],"sham",!0)}},{"../internals/create-non-enumerable-property":38,"../internals/fails":51,"../internals/redefine":109,"../internals/regexp-exec":111,"../internals/well-known-symbol":149,"../modules/es.regexp.exec":192}],53:[function(t,x,v){function s(g,p,n,i,a,h,y,l){for(var f,m=a,b=0,j=!!y&&c(y,l,3);b>1,j=n===23?u(2,-24)-u(2,-77):0,M=p<0||p===0&&1/p<0?1:0,E=0;for((p=s(p))!=p||p===1/0?(h=p!=p?1:0,a=m):(a=o(c(p)/g),p*(y=u(2,-a))<1&&(a--,y*=2),2<=(p+=1<=a+b?j/y:j*u(2,1-b))*y&&(a++,y/=2),m<=a+b?(h=0,a=m):1<=a+b?(h=(p*y-1)*u(2,n),a+=b):(h=p*u(2,b-1)*u(2,n),a=0));8<=n;l[E++]=255&h,h/=256,n-=8);for(a=a<>1,l=m-7,f=a-1,m=p[f--],b=127&m;for(m>>=7;0>=-l,l+=n;0"+b+""},m=function(){try{u=document.domain&&new ActiveXObject("htmlfile")}catch{}m=u?((b=u).write(f("")),b.close(),j=b.parentWindow.Object,b=null,j):(b=i("iframe"),j="java"+y+":",b.style.display="none",n.appendChild(b),b.src=String(j),(j=b.contentWindow.document).open(),j.write(f("document.F=Object")),j.close(),j.F);for(var b,j,M=g.length;M--;)delete m[h][g[M]];return m()};p[l]=!0,x.exports=Object.create||function(b,j){var M;return b!==null?(s[h]=o(b),M=new s,s[h]=null,M[l]=b):M=m(),j===void 0?M:c(M,j)}},{"../internals/an-object":10,"../internals/document-create-element":44,"../internals/enum-bug-keys":49,"../internals/hidden-keys":62,"../internals/html":64,"../internals/object-define-properties":92,"../internals/shared-key":119}],92:[function(t,x,v){var s=t("../internals/descriptors"),u=t("../internals/object-define-property"),o=t("../internals/an-object"),c=t("../internals/object-keys");x.exports=s?Object.defineProperties:function(g,p){o(g);for(var n,i=c(p),a=i.length,h=0;ha;)!s(i,n=p[a++])||~o(h,n)||h.push(n);return h}},{"../internals/array-includes":18,"../internals/has":61,"../internals/hidden-keys":62,"../internals/to-indexed-object":135}],100:[function(t,x,v){var s=t("../internals/object-keys-internal"),u=t("../internals/enum-bug-keys");x.exports=Object.keys||function(o){return s(o,u)}},{"../internals/enum-bug-keys":49,"../internals/object-keys-internal":99}],101:[function(t,x,v){var s={}.propertyIsEnumerable,u=Object.getOwnPropertyDescriptor,o=u&&!s.call({1:2},1);v.f=o?function(c){return c=u(this,c),!!c&&c.enumerable}:s},{}],102:[function(t,x,v){var s=t("../internals/an-object"),u=t("../internals/a-possible-prototype");x.exports=Object.setPrototypeOf||("__proto__"in{}?function(){var o,c=!1,g={};try{(o=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set).call(g,[]),c=g instanceof Array}catch{}return function(p,n){return s(p),u(n),c?o.call(p,n):p.__proto__=n,p}}():void 0)},{"../internals/a-possible-prototype":6,"../internals/an-object":10}],103:[function(t,x,v){var s=t("../internals/to-string-tag-support"),u=t("../internals/classof");x.exports=s?{}.toString:function(){return"[object "+u(this)+"]"}},{"../internals/classof":29,"../internals/to-string-tag-support":142}],104:[function(t,x,v){var s=t("../internals/get-built-in"),u=t("../internals/object-get-own-property-names"),o=t("../internals/object-get-own-property-symbols"),c=t("../internals/an-object");x.exports=s("Reflect","ownKeys")||function(g){var p=u.f(c(g)),n=o.f;return n?p.concat(n(g)):p}},{"../internals/an-object":10,"../internals/get-built-in":57,"../internals/object-get-own-property-names":96,"../internals/object-get-own-property-symbols":97}],105:[function(t,x,v){t=t("../internals/global"),x.exports=t},{"../internals/global":60}],106:[function(t,x,v){x.exports=function(s){try{return{error:!1,value:s()}}catch(u){return{error:!0,value:u}}}},{}],107:[function(t,x,v){var s=t("../internals/an-object"),u=t("../internals/is-object"),o=t("../internals/new-promise-capability");x.exports=function(c,g){return s(c),u(g)&&g.constructor===c?g:((0,(c=o.f(c)).resolve)(g),c.promise)}},{"../internals/an-object":10,"../internals/is-object":75,"../internals/new-promise-capability":87}],108:[function(t,x,v){var s=t("../internals/redefine");x.exports=function(u,o,c){for(var g in o)s(u,g,o[g],c);return u}},{"../internals/redefine":109}],109:[function(p,x,v){var s=p("../internals/global"),u=p("../internals/create-non-enumerable-property"),o=p("../internals/has"),c=p("../internals/set-global"),g=p("../internals/inspect-source"),p=p("../internals/internal-state"),n=p.get,i=p.enforce,a=String(String).split("String");(x.exports=function(h,y,l,j){var m=!!j&&!!j.unsafe,b=!!j&&!!j.enumerable,j=!!j&&!!j.noTargetGet;typeof l=="function"&&(typeof y!="string"||o(l,"name")||u(l,"name",y),i(l).source=a.join(typeof y=="string"?y:"")),h===s?b?h[y]=l:c(y,l):(m?!j&&h[y]&&(b=!0):delete h[y],b?h[y]=l:u(h,y,l))})(Function.prototype,"toString",function(){return typeof this=="function"&&n(this).source||g(this)})},{"../internals/create-non-enumerable-property":38,"../internals/global":60,"../internals/has":61,"../internals/inspect-source":69,"../internals/internal-state":71,"../internals/set-global":116}],110:[function(t,x,v){var s=t("./classof-raw"),u=t("./regexp-exec");x.exports=function(o,c){var g=o.exec;if(typeof g=="function"){if(g=g.call(o,c),typeof g!="object")throw TypeError("RegExp exec method returned something other than an Object or null");return g}if(s(o)!=="RegExp")throw TypeError("RegExp#exec called on incompatible receiver");return u.call(o,c)}},{"./classof-raw":28,"./regexp-exec":111}],111:[function(c,x,v){var s,u,o=c("./regexp-flags"),c=c("./regexp-sticky-helpers"),g=RegExp.prototype.exec,p=String.prototype.replace,n=g,i=(s=/a/,u=/b*/g,g.call(s,"a"),g.call(u,"a"),s.lastIndex!==0||u.lastIndex!==0),a=c.UNSUPPORTED_Y||c.BROKEN_CARET,h=/()??/.exec("")[1]!==void 0;x.exports=n=i||h||a?function(y){var l,f,m,b,j=this,M=a&&j.sticky,E=o.call(j),k=j.source,P=0,L=y;return M&&((E=E.replace("y","")).indexOf("g")===-1&&(E+="g"),L=String(y).slice(j.lastIndex),0f&&(y=y.slice(0,f)),p?h+y:y+h)}}var u=t("../internals/to-length"),o=t("../internals/string-repeat"),c=t("../internals/require-object-coercible"),g=Math.ceil;x.exports={start:s(!1),end:s(!0)}},{"../internals/require-object-coercible":114,"../internals/string-repeat":128,"../internals/to-length":137}],127:[function(t,x,v){function s(m){return m+22+75*(m<26)}function u(m){var b,j=[],M=(m=function(K){for(var ee=[],ue=0,T=K.length;uel((o-k)/N))throw RangeError(h);for(k+=(I-E)*N,E=I,A=0;Ao)throw RangeError(h);if(b==E){for(var F=k,B=c;;B+=c){var q=B<=P?1:P+g<=B?g:B-P;if(F>1,K+=l(K/ee);y*g>>1>>=1)&&(c+=c))1&p&&(g+=c);return g}},{"../internals/require-object-coercible":114,"../internals/to-integer":136}],129:[function(t,x,v){var s=t("../internals/fails"),u=t("../internals/whitespaces");x.exports=function(o){return s(function(){return!!u[o]()||"​…᠎"[o]()!="​…᠎"||u[o].name!==o})}},{"../internals/fails":51,"../internals/whitespaces":150}],130:[function(o,x,v){function s(p){return function(n){return n=String(u(n)),1&p&&(n=n.replace(c,"")),n=2&p?n.replace(g,""):n}}var u=o("../internals/require-object-coercible"),o="["+o("../internals/whitespaces")+"]",c=RegExp("^"+o+o+"*"),g=RegExp(o+o+"*$");x.exports={start:s(1),end:s(2),trim:s(3)}},{"../internals/require-object-coercible":114,"../internals/whitespaces":150}],131:[function(y,x,v){function s(C){return function(){L(C)}}function u(C){L(C.data)}function o(C){g.postMessage(C+"",l.protocol+"//"+l.host)}var c,g=y("../internals/global"),p=y("../internals/fails"),n=y("../internals/classof-raw"),i=y("../internals/function-bind-context"),a=y("../internals/html"),h=y("../internals/document-create-element"),y=y("../internals/engine-is-ios"),l=g.location,f=g.setImmediate,m=g.clearImmediate,b=g.process,j=g.MessageChannel,M=g.Dispatch,E=0,k={},P="onreadystatechange",L=function(C){var I;k.hasOwnProperty(C)&&(I=k[C],delete k[C],I())};f&&m||(f=function(C){for(var I=[],A=1;A=h.length?{value:a.target=void 0,done:!0}:y=="keys"?{value:l,done:!1}:y=="values"?{value:h[l],done:!1}:{value:[l,h[l]],done:!1}},"values"),o.Arguments=o.Array,u("keys"),u("values"),u("entries")},{"../internals/add-to-unscopables":7,"../internals/define-iterator":41,"../internals/internal-state":71,"../internals/iterators":80,"../internals/to-indexed-object":135}],165:[function(g,x,v){var s=g("../internals/export"),c=g("../internals/indexed-object"),u=g("../internals/to-indexed-object"),g=g("../internals/array-method-is-strict"),o=[].join,c=c!=Object,g=g("join",",");s({target:"Array",proto:!0,forced:c||!g},{join:function(p){return o.call(u(this),p===void 0?",":p)}})},{"../internals/array-method-is-strict":22,"../internals/export":50,"../internals/indexed-object":67,"../internals/to-indexed-object":135}],166:[function(u,x,v){var s=u("../internals/export"),u=u("../internals/array-last-index-of");s({target:"Array",proto:!0,forced:u!==[].lastIndexOf},{lastIndexOf:u})},{"../internals/array-last-index-of":20,"../internals/export":50}],167:[function(c,x,v){var s=c("../internals/export"),u=c("../internals/array-iteration").map,o=c("../internals/array-method-has-species-support"),c=c("../internals/array-method-uses-to-length"),o=o("map"),c=c("map");s({target:"Array",proto:!0,forced:!o||!c},{map:function(g){return u(this,g,1I;I++)p(M,P=C[I])&&!p(L,P)&&m(L,P,f(M,P));(L.prototype=E).constructor=L,g(o,j,L)}},{"../internals/classof-raw":28,"../internals/descriptors":43,"../internals/fails":51,"../internals/global":60,"../internals/has":61,"../internals/inherit-if-required":68,"../internals/is-forced":74,"../internals/object-create":91,"../internals/object-define-property":93,"../internals/object-get-own-property-descriptor":94,"../internals/object-get-own-property-names":96,"../internals/redefine":109,"../internals/string-trim":130,"../internals/to-primitive":141}],179:[function(t,x,v){t("../internals/export")({target:"Number",stat:!0},{isFinite:t("../internals/number-is-finite")})},{"../internals/export":50,"../internals/number-is-finite":89}],180:[function(p,x,v){function s(a,h,y){return h===0?y:h%2==1?s(a,h-1,y*a):s(a*a,h/2,y)}var u=p("../internals/export"),o=p("../internals/to-integer"),c=p("../internals/this-number-value"),g=p("../internals/string-repeat"),p=p("../internals/fails"),n=1 .toFixed,i=Math.floor;u({target:"Number",proto:!0,forced:n&&(8e-5.toFixed(3)!=="0.000"||.9.toFixed(0)!=="1"||1.255.toFixed(2)!=="1.25"||0xde0b6b3a7640080.toFixed(0)!=="1000000000000000128")||!p(function(){n.call({})})},{toFixed:function(j){function h(P,L){for(var C=-1,I=L;++C<6;)I+=P*M[C],M[C]=I%1e7,I=i(I/1e7)}function y(P){for(var L=6,C=0;0<=--L;)C+=M[L],M[L]=i(C/P),C=C%P*1e7}function l(){for(var P,L=6,C="";0<=--L;)C===""&&L!==0&&M[L]===0||(P=String(M[L]),C=C===""?P:C+g.call("0",7-P.length)+P);return C}var f,m,b=c(this),j=o(j),M=[0,0,0,0,0,0],E="",k="0";if(j<0||20Pe;){var He,We,qe,Ye=se[Pe++],lt=Se?Ye.ok:Ye.fail,ot=Ye.resolve,Ke=Ye.reject,it=Ye.domain;try{lt?(Se||(Ee.rejection===ye&&function(nt,Mt){C.call(n,function(){pe?J.emit("rejectionHandled",nt):De(te,nt,Mt.value)})}(Re,Ee),Ee.rejection=de),lt===!0?He=xe:(it&&it.enter(),He=lt(xe),it&&(it.exit(),qe=!0)),He===Ye.promise?Ke(W("Promise-chain cycle")):(We=be(He))?We.call(He,ot,Ke):ot(He)):Ke(xe)}catch(nt){it&&!qe&&it.exit(),Ke(nt)}}Ee.reactions=[],Ee.notified=!1,re&&!Ee.rejection&&(Q=Re,ae=Ee,C.call(n,function(){var nt=ae.value,Mt=Le(ae);if(Mt&&(Mt=B(function(){pe?J.emit("unhandledRejection",nt,Q):De(z,Q,nt)}),ae.rejection=pe||Le(ae)?ye:de,Mt.error))throw Mt.value}))}))},De=function(Re,Ee,re){var se;Z?((se=$.createEvent("Event")).promise=Ee,se.reason=re,se.initEvent(Re,!1,!0),n.dispatchEvent(se)):se={promise:Ee,reason:re},(Ee=n["on"+Re])?Ee(se):Re===z&&N("Unhandled promise rejection",re)},Le=function(Re){return Re.rejection!==de&&!Re.parent},Ne=function(Re,Ee,re,se){return function(Q){Re(Ee,re,Q,se)}},Be=function(Re,Ee,re,se){Ee.done||(Ee.done=!0,(Ee=se||Ee).value=re,Ee.state=me,Ie(Re,Ee,!0))},we=function(Re,Ee,re,se){if(!Ee.done){Ee.done=!0,se&&(Ee=se);try{if(Re===re)throw W("Promise can't be resolved itself");var Q=be(re);Q?I(function(){var ae={done:!1};try{Q.call(re,Ne(we,Re,ae,Ee),Ne(Be,Re,ae,Ee))}catch(xe){Be(Re,ae,xe,Ee)}}):(Ee.value=re,Ee.state=le,Ie(Re,Ee,!1))}catch(ae){Be(Re,{done:!1},ae,Ee)}}};ge&&(G=function(Re){j(this,G,ee),b(Re),s.call(this);var Ee=ue(this);try{Re(Ne(we,this,Ee),Ne(Be,this,Ee))}catch(re){Be(this,Ee,re)}},(s=function(Re){T(this,{type:ee,done:!1,notified:!1,parent:!1,reactions:[],rejection:!1,state:0,value:void 0})}).prototype=y(G.prototype,{then:function(Re,Ee){var re=D(this),se=ce(L(this,G));return se.ok=typeof Re!="function"||Re,se.fail=typeof Ee=="function"&&Ee,se.domain=pe?J.domain:void 0,re.parent=!0,re.reactions.push(se),re.state!=0&&Ie(this,re,!1),se.promise},catch:function(Re){return this.then(void 0,Re)}}),u=function(){var Re=new s,Ee=ue(Re);this.promise=Re,this.resolve=Ne(we,Re,Ee),this.reject=Ne(Be,Re,Ee)},F.f=ce=function(Re){return Re===G||Re===o?new u:ie(Re)},p||typeof a!="function"||(c=a.prototype.then,h(a.prototype,"then",function(Re,Ee){var re=this;return new G(function(se,Q){c.call(re,se,Q)}).then(Re,Ee)},{unsafe:!0}),typeof ne=="function"&&g({global:!0,enumerable:!0,forced:!0},{fetch:function(Re){return A(G,ne.apply(n,arguments))}}))),g({global:!0,wrap:!0,forced:ge},{Promise:G}),l(G,ee,!1,!0),f(ee),o=i(ee),g({target:ee,stat:!0,forced:ge},{reject:function(Re){var Ee=ce(this);return Ee.reject.call(void 0,Re),Ee.promise}}),g({target:ee,stat:!0,forced:p||ge},{resolve:function(Re){return A(p&&this===o?G:this,Re)}}),g({target:ee,stat:!0,forced:Me},{all:function(Re){var Ee=this,re=ce(Ee),se=re.resolve,Q=re.reject,ae=B(function(){var xe=b(Ee.resolve),Se=[],Pe=0,He=1;k(Re,function(We){var qe=Pe++,Ye=!1;Se.push(void 0),He++,xe.call(Ee,We).then(function(lt){Ye||(Ye=!0,Se[qe]=lt,--He||se(Se))},Q)}),--He||se(Se)});return ae.error&&Q(ae.value),re.promise},race:function(Re){var Ee=this,re=ce(Ee),se=re.reject,Q=B(function(){var ae=b(Ee.resolve);k(Re,function(xe){ae.call(Ee,xe).then(re.resolve,se)})});return Q.error&&se(Q.value),re.promise}})},{"../internals/a-function":5,"../internals/an-instance":9,"../internals/check-correctness-of-iteration":27,"../internals/classof-raw":28,"../internals/engine-v8-version":48,"../internals/export":50,"../internals/get-built-in":57,"../internals/global":60,"../internals/host-report-errors":63,"../internals/inspect-source":69,"../internals/internal-state":71,"../internals/is-forced":74,"../internals/is-object":75,"../internals/is-pure":76,"../internals/iterate":78,"../internals/microtask":82,"../internals/native-promise-constructor":83,"../internals/new-promise-capability":87,"../internals/perform":106,"../internals/promise-resolve":107,"../internals/redefine":109,"../internals/redefine-all":108,"../internals/set-species":117,"../internals/set-to-string-tag":118,"../internals/species-constructor":122,"../internals/task":131,"../internals/well-known-symbol":149}],189:[function(n,x,v){var s=n("../internals/export"),y=n("../internals/get-built-in"),u=n("../internals/a-function"),o=n("../internals/an-object"),c=n("../internals/is-object"),g=n("../internals/object-create"),p=n("../internals/function-bind"),n=n("../internals/fails"),i=y("Reflect","construct"),a=n(function(){function l(){}return!(i(function(){},[],l)instanceof l)}),h=!n(function(){i(function(){})}),y=a||h;s({target:"Reflect",stat:!0,forced:y,sham:y},{construct:function(l,f){u(l),o(f);var m=arguments.length<3?l:u(arguments[2]);if(h&&!a)return i(l,f,m);if(l==m){switch(f.length){case 0:return new l;case 1:return new l(f[0]);case 2:return new l(f[0],f[1]);case 3:return new l(f[0],f[1],f[2]);case 4:return new l(f[0],f[1],f[2],f[3])}var b=[null];return b.push.apply(b,f),new(p.apply(l,b))}return b=m.prototype,m=g(c(b)?b:Object.prototype),b=Function.apply.call(l,m,f),c(b)?b:m}})},{"../internals/a-function":5,"../internals/an-object":10,"../internals/export":50,"../internals/fails":51,"../internals/function-bind":56,"../internals/get-built-in":57,"../internals/is-object":75,"../internals/object-create":91}],190:[function(t,x,v){var s=t("../internals/export"),u=t("../internals/is-object"),o=t("../internals/an-object"),c=t("../internals/has"),g=t("../internals/object-get-own-property-descriptor"),p=t("../internals/object-get-prototype-of");s({target:"Reflect",stat:!0},{get:function n(i,a){var h,y=arguments.length<3?i:arguments[2];return o(i)===y?i[a]:(h=g.f(i,a))?c(h,"value")?h.value:h.get===void 0?void 0:h.get.call(y):u(h=p(i))?n(h,a,y):void 0}})},{"../internals/an-object":10,"../internals/export":50,"../internals/has":61,"../internals/is-object":75,"../internals/object-get-own-property-descriptor":94,"../internals/object-get-prototype-of":98}],191:[function(t,x,v){var s=t("../internals/descriptors"),u=t("../internals/global"),o=t("../internals/is-forced"),c=t("../internals/inherit-if-required"),g=t("../internals/object-define-property").f,p=t("../internals/object-get-own-property-names").f,n=t("../internals/is-regexp"),i=t("../internals/regexp-flags"),a=t("../internals/regexp-sticky-helpers"),h=t("../internals/redefine"),y=t("../internals/fails"),l=t("../internals/internal-state").set,f=t("../internals/set-species"),m=t("../internals/well-known-symbol")("match"),b=u.RegExp,j=b.prototype,M=/a/g,E=/a/g,k=new b(M)!==M,P=a.UNSUPPORTED_Y;if(s&&o("RegExp",!k||P||y(function(){return E[m]=!1,b(M)!=M||b(E)==E||b(M,"i")!="/a/i"}))){for(var L=function(A,N){var F,B=this instanceof L,q=n(A),V=N===void 0;return!B&&q&&A.constructor===L&&V?A:(k?q&&!V&&(A=A.source):A instanceof L&&(V&&(N=i.call(A)),A=A.source),P&&(F=!!N&&-1I;)(function(A){A in L||g(L,A,{configurable:!0,get:function(){return b[A]},set:function(N){b[A]=N}})})(C[I++]);(j.constructor=L).prototype=j,h(u,"RegExp",L)}f("RegExp")},{"../internals/descriptors":43,"../internals/fails":51,"../internals/global":60,"../internals/inherit-if-required":68,"../internals/internal-state":71,"../internals/is-forced":74,"../internals/is-regexp":77,"../internals/object-define-property":93,"../internals/object-get-own-property-names":96,"../internals/redefine":109,"../internals/regexp-flags":112,"../internals/regexp-sticky-helpers":113,"../internals/set-species":117,"../internals/well-known-symbol":149}],192:[function(u,x,v){var s=u("../internals/export"),u=u("../internals/regexp-exec");s({target:"RegExp",proto:!0,forced:/./.exec!==u},{exec:u})},{"../internals/export":50,"../internals/regexp-exec":111}],193:[function(c,x,v){var s=c("../internals/redefine"),u=c("../internals/an-object"),n=c("../internals/fails"),o=c("../internals/regexp-flags"),c="toString",g=RegExp.prototype,p=g[c],n=n(function(){return p.call({source:"a",flags:"b"})!="/a/b"}),i=p.name!=c;(n||i)&&s(RegExp.prototype,c,function(){var a=u(this),h=String(a.source),y=a.flags;return"/"+h+"/"+String(y===void 0&&a instanceof RegExp&&!("flags"in g)?o.call(a):y)},{unsafe:!0})},{"../internals/an-object":10,"../internals/fails":51,"../internals/redefine":109,"../internals/regexp-flags":112}],194:[function(u,x,v){var s=u("../internals/collection"),u=u("../internals/collection-strong");x.exports=s("Set",function(o){return function(){return o(this,arguments.length?arguments[0]:void 0)}},u)},{"../internals/collection":32,"../internals/collection-strong":30}],195:[function(p,x,v){var s=p("../internals/export"),u=p("../internals/object-get-own-property-descriptor").f,o=p("../internals/to-length"),c=p("../internals/not-a-regexp"),g=p("../internals/require-object-coercible"),a=p("../internals/correct-is-regexp-logic"),p=p("../internals/is-pure"),n="".endsWith,i=Math.min,a=a("endsWith");s({target:"String",proto:!0,forced:!!(p||a||!(s=u(String.prototype,"endsWith"))||s.writable)&&!a},{endsWith:function(h){var y=String(g(this)),l=(c(h),1=i.length?{value:void 0,done:!0}:(i=s(i,a),n.index+=i.length,{value:i,done:!1})})},{"../internals/define-iterator":41,"../internals/internal-state":71,"../internals/string-multibyte":124}],198:[function(t,x,v){var s=t("../internals/fix-regexp-well-known-symbol-logic"),u=t("../internals/an-object"),o=t("../internals/to-length"),c=t("../internals/require-object-coercible"),g=t("../internals/advance-string-index"),p=t("../internals/regexp-exec-abstract");s("match",1,function(n,i,a){return[function(h){var y=c(this),l=h==null?void 0:h[n];return l!==void 0?l.call(h,y):new RegExp(h)[n](String(y))},function(h){var y=a(i,h,this);if(y.done)return y.value;var l=u(h),f=String(this);if(!l.global)return p(l,f);for(var m=l.unicode,b=[],j=l.lastIndex=0;(M=p(l,f))!==null;){var M=String(M[0]);(b[j]=M)===""&&(l.lastIndex=g(f,o(l.lastIndex),m)),j++}return j===0?null:b}]})},{"../internals/advance-string-index":8,"../internals/an-object":10,"../internals/fix-regexp-well-known-symbol-logic":52,"../internals/regexp-exec-abstract":110,"../internals/require-object-coercible":114,"../internals/to-length":137}],199:[function(t,x,v){var s=t("../internals/export"),u=t("../internals/string-pad").start;s({target:"String",proto:!0,forced:t("../internals/string-pad-webkit-bug")},{padStart:function(o){return u(this,o,1]*>)/g,f=/\$([$&'`]|\d\d?)/g;s("replace",2,function(m,b,j,M){var E=M.REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE,k=M.REPLACE_KEEPS_$0,P=E?"$":"$0";return[function(L,C){var I=p(this),A=L==null?void 0:L[m];return A!==void 0?A.call(L,I,C):b.call(String(I),L,C)},function(L,C){if(!E&&k||typeof C=="string"&&C.indexOf(P)===-1){var I=j(b,L,this,C);if(I.done)return I.value}for(var A,N=u(L),F=String(this),B=typeof C=="function",q=(B||(C=String(C)),N.global),V=(q&&(A=N.unicode,N.lastIndex=0),[]);(T=i(N,F))!==null&&(V.push(T),q);)String(T[0])===""&&(N.lastIndex=n(F,c(N.lastIndex),A));for(var H,K="",ee=0,ue=0;ue>>0;if(C==0)return[];if(k===void 0)return[L];if(!u(k))return j.call(L,k,C);for(var I,A,N,F=[],P=(k.ignoreCase?"i":"")+(k.multiline?"m":"")+(k.unicode?"u":"")+(k.sticky?"y":""),B=0,q=new RegExp(k.source,P+"g");(I=a.call(q,L))&&!(B<(A=q.lastIndex)&&(F.push(L.slice(B,I.index)),1=C));)q.lastIndex===I.index&&q.lastIndex++;return B===L.length?!N&&q.test("")||F.push(""):F.push(L.slice(B)),F.length>C?F.slice(0,C):F}:"0".split(void 0,0).length?function(k,P){return k===void 0&&P===0?[]:j.call(this,k,P)}:j;return[function(k,P){var L=c(this),C=k==null?void 0:k[b];return C!==void 0?C.call(k,L,P):E.call(String(L),k,P)},function(I,P){var L=M(E,I,this,P,E!==j);if(L.done)return L.value;var L=o(I),C=String(this),I=g(L,RegExp),A=L.unicode,N=(L.ignoreCase?"i":"")+(L.multiline?"m":"")+(L.unicode?"u":"")+(m?"y":"g"),F=new I(m?L:"^(?:"+L.source+")",N),B=P===void 0?f:P>>>0;if(B==0)return[];if(C.length===0)return i(F,C)===null?[C]:[];for(var q=0,V=0,H=[];Vne.key){pe.splice(ce,0,ne);break}ce===z&&pe.push(ne)}ie.updateURL()},forEach:function(ne){for(var ce,ie=H(this).entries,pe=j(ne,16))return;for(Nt=0;Jt();){if(Qt=null,Nt>0)if(Jt()=="."&&Nt<4)$e++;else return;if(!G.test(Jt()))return;for(;G.test(Jt());){if(en=parseInt(Jt(),10),Qt===null)Qt=en;else{if(Qt==0)return;Qt=Qt*10+en}if(Qt>255)return;$e++}gt[Xe]=gt[Xe]*256+Qt,Nt++,(Nt==2||Nt==4)&&Xe++}if(Nt!=4)return;break}else if(Jt()==":"){if($e++,!Jt())return}else if(Jt())return;gt[Xe++]=Vt}if(pt!==null)for(_r=Xe-pt,Xe=7;Xe!=0&&_r>0;)tn=gt[Xe],gt[Xe--]=gt[pt+_r-1],gt[pt+--_r]=tn;else if(Xe!=8)return;return gt}(ze.slice(1,-1)))?void(_e.host=Ze):ee;if(be(_e))return ze=k(ze),ce.test(ze)||(Ze=function(Ge){var gt=Ge.split("."),Xe,pt,$e,Vt,$t,Nt,Qt;if(gt.length&>[gt.length-1]==""&>.pop(),(Xe=gt.length)>4)return Ge;for(pt=[],$e=0;$e1&&Vt.charAt(0)=="0"&&($t=W.test(Vt)?16:8,Vt=Vt.slice($t==8?1:2)),Vt==="")Nt=0;else{if(!($t==10?J:$t==8?$:ne).test(Vt))return Ge;Nt=parseInt(Vt,$t)}pt.push(Nt)}for($e=0;$e=V(256,5-Xe))return null}else if(Nt>255)return null;for(Qt=pt.pop(),$e=0;$e":1,"`":1}),de=j({},me,{"#":1,"?":1,"{":1,"}":1}),ye=j({},de,{"/":1,":":1,";":1,"=":1,"@":1,"[":1,"\\":1,"]":1,"^":1,"|":1}),ge=function(_e,ze){var Ze=E(_e,0);return 32"u"&&s!==void 0&&{}.toString.call(s)==="[object process]",m=typeof Uint8ClampedArray<"u"&&typeof importScripts<"u"&&typeof MessageChannel<"u";function b(){var z=setTimeout;return function(){return z(M,1)}}var j=new Array(1e3);function M(){for(var z=0;zL,applyPalette:()=>function(B,q,V="rgb565"){if(!B||!B.buffer)throw new Error("quantize() expected RGBA Uint8Array data");if(!(B instanceof Uint8Array||B instanceof Uint8ClampedArray))throw new Error("quantize() expected RGBA Uint8Array data");if(256>24&255,G=$>>16&255,W=$>>8&255,$=255&$,J=h($,W,G,D),J=J in T?T[J]:T[J]=function(z,te,le,me,de){let ye=0,ge=1e100;for(let De=0;Dege||(Me=be[0],(Ie+=E(Me-z))>ge||(Me=be[1],(Ie+=E(Me-te))>ge||(Me=be[2],(Ie+=E(Me-le))>ge||(ge=Ie,ye=De))))}return ye}($,W,G,D,q);ue[Z]=J}else{const Z=V==="rgb444"?y:a;for(let z=0;z>16&255,ce=ie>>8&255,ie=255&ie,pe=Z(ie,ce,ne),pe=pe in T?T[pe]:T[pe]=function(te,le,me,de){let ye=0,ge=1e100;for(let De=0;Dege||(Me=be[1],(Ie+=E(Me-le))>ge||(Me=be[2],(Ie+=E(Me-me))>ge||(ge=Ie,ye=De)))}return ye}(ie,ce,ne,q);ue[z]=pe}}return ue},default:()=>F,nearestColor:()=>function(B,q,V=j){return B[k(B,q,V)]},nearestColorIndex:()=>k,nearestColorIndexWithDistance:()=>P,prequantize:()=>function(B,{roundRGB:q=5,roundAlpha:V=10,oneBitAlpha:H=null}={}){const K=new Uint32Array(B.buffer);for(let G=0;G>24&255;var ee,ue=D>>16&255,T=D>>8&255,D=255&D;W=M(W,V),H&&(ee=typeof H=="number"?H:127,W=W<=ee?0:255),D=M(D,q),T=M(T,q),ue=M(ue,q),K[G]=W<<24|ue<<16|T<<8|D<<0}},quantize:()=>function(B,q,V={}){var{format:H="rgb565",clearAlpha:K=!0,clearAlphaColor:ee=0,clearAlphaThreshold:ue=0,oneBitAlpha:T=!1}=V;if(!B||!B.buffer)throw new Error("quantize() expected RGBA Uint8Array data");if(!(B instanceof Uint8Array||B instanceof Uint8ClampedArray))throw new Error("quantize() expected RGBA Uint8Array data");B=new Uint32Array(B.buffer);let D=V.useSqrt!==!1;const G=H==="rgba4444",W=function(Le,Ne){const Be=Ne==="rgb444"?4096:65536,we=new Array(Be),Re=Le.length;if(Ne==="rgba4444")for(let ot=0;ot>24&255,re=Q>>16&255,se=Q>>8&255,Q=255&Q,ae=h(Q,se,re,Ee);let Ke=ae in we?we[ae]:we[ae]=b();Ke.rc+=Q,Ke.gc+=se,Ke.bc+=re,Ke.ac+=Ee,Ke.cnt++}else if(Ne==="rgb444")for(let ot=0;ot>16&255,Se=Pe>>8&255,Pe=255&Pe,He=y(Pe,Se,xe);let Ke=He in we?we[He]:we[He]=b();Ke.rc+=Pe,Ke.gc+=Se,Ke.bc+=xe,Ke.cnt++}else for(let ot=0;ot>16&255,qe=Ye>>8&255,Ye=255&Ye,lt=a(Ye,qe,We);let Ke=lt in we?we[lt]:we[lt]=b();Ke.rc+=Ye,Ke.gc+=qe,Ke.bc+=We,Ke.cnt++}return we}(B,H),$=W.length,J=$-1,ne=new Uint32Array($+1);for(var ce=0,ie=0;ie<$;++ie){const Le=W[ie];Le!=null&&(be=1/Le.cnt,G&&(Le.ac*=be),Le.rc*=be,Le.gc*=be,Le.bc*=be,W[ce++]=Le)}f(q)/ce<.022&&(D=!1);for(var pe,Z,z,ie=0;ie>1,!(W[pe=ne[z]].err<=te));Z=z)ne[Z]=pe;ne[Z]=ie}var le,me=ce-q;for(ie=0;ie=le.mtm&&W[le.nn].mtm<=le.tm)break;for(le.mtm==J?de=ne[1]=ne[ne[0]--]:(m(W,de),le.tm=ie),te=W[de].err,Z=1;(z=Z+Z)<=ne[0]&&(zW[ne[z+1]].err&&z++,!(te<=W[pe=ne[z]].err));Z=z)ne[Z]=pe;ne[Z]=de}var ye=W[le.nn],ge=le.cnt,Me=ye.cnt,be=1/(ge+Me);G&&(le.ac=be*(ge*le.ac+Me*ye.ac)),le.rc=be*(ge*le.rc+Me*ye.rc),le.gc=be*(ge*le.gc+Me*ye.gc),le.bc=be*(ge*le.bc+Me*ye.bc),le.cnt+=ye.cnt,le.mtm=++ie,W[ye.bk].fw=ye.fw,W[ye.fw].bk=ye.bk,ye.mtm=J}let Ie=[];for(ie=0;;0){let Le=l(Math.round(W[ie].rc),0,255),Ne=l(Math.round(W[ie].gc),0,255),Be=l(Math.round(W[ie].bc),0,255),we=255;G&&(we=l(Math.round(W[ie].ac),0,255),T&&(De=typeof T=="number"?T:127,we=we<=De?0:255),K&&we<=ue&&(Le=Ne=Be=ee,we=0));var De=G?[Le,Ne,Be,we]:[Le,Ne,Be];if(function(Re,Ee){for(let Q=0;Qfunction(B,q,V=5){if(B.length&&q.length){var H=B.map(D=>D.slice(0,3)),K=V*V,ee=B[0].length;for(let D=0;Dee?G.slice(0,3):G.slice();var T=P(H,G.slice(0,3),j),ue=T[0],T=T[1];0>>0),ee!=0&&(K=Math.max(K,256));const ue=V;V=new Uint8Array(K),0>=8,$-=8;if((te>pe||ce)&&(ce?(ie=ne,pe=(1<>=8,$-=8;0>3}function h(B,q,V,H){return B>>4|240&q|(240&V)<<4|(240&H)<<8}function y(B,q,V){return B>>4<<8|240&q|V>>4}function l(B,q,V){return B>8&255)}function A(B,q){for(var V=0;V>1,y=-7,l=o?m-1:0,f=o?-1:1,m=s[u+l];for(l+=f,p=m&(1<<-y)-1,m>>=-y,y+=i;0>=-y,y+=c;0>1,l=g===23?Math.pow(2,-24)-Math.pow(2,-77):0,f=c?0:b-1,m=c?1:-1,b=u<0||u===0&&1/u<0?1:0;for(u=Math.abs(u),isNaN(u)||u===1/0?(i=isNaN(u)?1:0,n=h):(n=Math.floor(Math.log(u)/Math.LN2),u*(c=Math.pow(2,-n))<1&&(n--,c*=2),2<=(u+=1<=n+y?l/c:l*Math.pow(2,1-y))*c&&(n++,c/=2),h<=n+y?(i=0,n=h):1<=n+y?(i=(u*c-1)*Math.pow(2,g),n+=y):(i=u*Math.pow(2,y-1)*Math.pow(2,g),n=0));8<=g;s[o+f]=255&i,f+=m,i/=256,g-=8);for(n=n<Math.abs(re[0])&&(se=1),se=Math.abs(re[2])>Math.abs(re[se])?2:se}function I(re,se){re.f+=se.f,re.b.f+=se.b.f}function A(re,se,Q){return re=re.a,se=se.a,Q=Q.a,se.b.a===re?Q.b.a===re?o(se.a,Q.a)?g(Q.b.a,se.a,Q.a)<=0:0<=g(se.b.a,Q.a,se.a):g(Q.b.a,re,Q.a)<=0:Q.b.a===re?0<=g(se.b.a,re,se.a):(se=c(se.b.a,re,se.a),(re=c(Q.b.a,re,Q.a))<=se)}function N(re){re.a.i=null;var se=re.e;se.a.c=se.c,se.c.a=se.a,re.e=null}function F(re,se){l(re.a),re.c=!1,(re.a=se).i=re}function B(re){for(var se=re.a.a;(re=Ee(re)).a.a===se;);return re.c&&(F(re,se=m(Re(re).a.b,re.a.e)),re=Ee(re)),re}function q(re,se,Q){var ae=new we;return ae.a=Q,ae.e=ce(re.f,se.e,ae),Q.i=ae}function V(re,se){switch(re.s){case 100130:return(1&se)!=0;case 100131:return se!==0;case 100132:return 0>1]],He[Pe[qe]])?Ne:Be)(Q,qe),He[Se]=null,We[Se]=Q.b,Q.b=Se}else for(Q.c[-(Se+1)]=null;0Math.max(Pe.a,We.a))){if(o(Se,Pe)){if(0Q.f&&(Q.f*=2,Q.c=Ie(Q.c,Q.f+1)),Q.b===0?xe=ae:(xe=Q.b,Q.b=Q.c[Q.b]),Q.e[xe]=se,Q.c[xe]=ae,Q.d[ae]=xe,Q.h&&Be(Q,ae),xe):(Q=re.a++,re.c[Q]=se,-(Q+1))}function Me(re){if(re.a===0)return Le(re.b);var se=re.c[re.d[re.a-1]];if(re.b.a!==0&&o(De(re.b),se))return Le(re.b);for(;--re.a,0re.a||o(ae[Pe],ae[We])){xe[Q[Se]=Pe]=Se;break}xe[Q[Se]=We]=Se,Se=He}}function Be(re,se){for(var Q=re.d,ae=re.e,xe=re.c,Se=se,Pe=Q[Se];;){var He=Se>>1,We=Q[He];if(He==0||o(ae[We],ae[Pe])){xe[Q[Se]=Pe]=Se;break}xe[Q[Se]=We]=Se,Se=He}}function we(){this.e=this.a=null,this.f=0,this.c=this.b=this.h=this.d=!1}function Re(re){return re.e.c.b}function Ee(re){return re.e.a.b}(s=pe.prototype).x=function(){Z(this,0)},s.B=function(re,se){switch(re){case 100142:return;case 100140:switch(se){case 100130:case 100131:case 100132:case 100133:case 100134:return void(this.s=se)}break;case 100141:return void(this.m=!!se);default:return void z(this,100900)}z(this,100901)},s.y=function(re){switch(re){case 100142:return 0;case 100140:return this.s;case 100141:return this.m;default:z(this,100900)}return!1},s.A=function(re,se,Q){this.j[0]=re,this.j[1]=se,this.j[2]=Q},s.z=function(re,se){var Q=se||null;switch(re){case 100100:case 100106:this.h=Q;break;case 100104:case 100110:this.l=Q;break;case 100101:case 100107:this.k=Q;break;case 100102:case 100108:this.i=Q;break;case 100103:case 100109:this.p=Q;break;case 100105:case 100111:this.o=Q;break;case 100112:this.r=Q;break;default:z(this,100900)}},s.C=function(re,se){var Q=!1,ae=[0,0,0];Z(this,2);for(var xe=0;xe<3;++xe){var Se=re[xe];Se<-1e150&&(Se=-1e150,Q=!0),1e150ae[qe]&&(ae[qe]=Ye,xe[qe]=Q)}if(ae[1]-He[1]>ae[Q=0]-He[0]&&(Q=1),He[Q=ae[2]-He[2]>ae[Q]-He[Q]?2:Q]>=ae[Q])Pe[0]=0,Pe[1]=0,Pe[2]=1;else{for(He=We[Q],xe=xe[Q],We=[ae=0,0,0],He=[He.g[0]-xe.g[0],He.g[1]-xe.g[1],He.g[2]-xe.g[2]],qe=[0,0,0],Q=Se.e;Q!==Se;Q=Q.e)qe[0]=Q.g[0]-xe.g[0],qe[1]=Q.g[1]-xe.g[1],qe[2]=Q.g[2]-xe.g[2],We[0]=He[1]*qe[2]-He[2]*qe[1],We[1]=He[2]*qe[0]-He[0]*qe[2],We[2]=He[0]*qe[1]-He[1]*qe[0],ae<(Ye=We[0]*We[0]+We[1]*We[1]+We[2]*We[2])&&(ae=Ye,Pe[0]=We[0],Pe[1]=We[1],Pe[2]=We[2]);ae<=0&&(Pe[0]=Pe[1]=Pe[2]=0,Pe[C(He)]=1)}Se=!0}for(We=C(Pe),Q=this.b.c,ae=(We+1)%3,xe=(We+2)%3,We=0>=1;)++y;if(f=1<>8&255,o[n++]=255&g,o[n++]=g>>8&255,o[n++]=(a!==null?128:0)|y,o[n++]=l,o[n++]=0,a!==null)for(var m=0,b=a.length;m>16&255,o[n++]=j>>8&255,o[n++]=255&j}if(i!==null){if(i<0||65535>8&255,o[n++]=0}var M=!1;this.addFrame=function(E,k,P,L,C,I){if(M===!0&&(--n,M=!1),I=I===void 0?{}:I,E<0||k<0||65535>=1;)++F;var B=1<>8&255,o[n++]=K,o[n++]=0),o[n++]=44,o[n++]=255&E,o[n++]=E>>8&255,o[n++]=255&k,o[n++]=k>>8&255,o[n++]=255&P,o[n++]=P>>8&255,o[n++]=255&L,o[n++]=L>>8&255,o[n++]=A===!0?128|F-1:0,A===!0)for(var ee=0,ue=N.length;ee>16&255,o[n++]=T>>8&255,o[n++]=255&T}return n=function(D,G,W,$){D[G++]=W;var J=G++,ne=1<>=8,z-=8,G===J+256&&(D[J]=255,J=G++)}function me(Le){te|=Le<>=8,z-=8,G===J+256&&(D[J]=255,J=G++);pe===4096?(me(ne),pe=1+ie,Z=W+1,ye={}):(1<>=y,f-=y,k==i)h=1+a,l=(1<<(y=n+1))-1,E=null;else{if(k==a)break;for(var P=k>8,++L;var I=C;if(p>=8;E!==null&&h<4096&&(M[h++]=E<<8|I,l+1<=h&&y<12&&(++y,l=l<<1|1)),E=k}}b!==p&&console.log("Warning, gif stream shorter than expected.")}try{v.GifWriter=s,v.GifReader=function(o){var c=0;if(o[c++]!==71||o[c++]!==73||o[c++]!==70||o[c++]!==56||(o[c++]+1&253)!=56||o[c++]!==97)throw new Error("Invalid GIF 87a/89a header.");var g=o[c++]|o[c++]<<8,p=o[c++]|o[c++]<<8,n=o[c++],i=1<<1+(7&n),a=(o[c++],o[c++],null),h=null,y=(n>>7&&(a=c,c+=3*(h=i)),!0),l=[],f=0,m=null,b=0,j=null;for(this.width=g,this.height=p;y&&c>2&7,c++;break;case 254:for(;;){if(!(0<=(E=o[c++])))throw Error("Invalid block size");if(E===0)break;c+=E}break;default:throw new Error("Unknown graphic control label: 0x"+o[c-1].toString(16))}break;case 44:var E,k=o[c++]|o[c++]<<8,P=o[c++]|o[c++]<<8,L=o[c++]|o[c++]<<8,C=o[c++]|o[c++]<<8,q=o[c++],I=q>>6&1,A=1<<1+(7&q),N=a,F=h,B=!1,q=(q>>7&&(B=!0,N=c,c+=3*(F=A)),c);for(c++;;){if(!(0<=(E=o[c++])))throw Error("Invalid block size");if(E===0)break;c+=E}l.push({x:k,y:P,width:L,height:C,has_local_palette:B,palette_offset:N,palette_size:F,data_offset:q,data_length:c-q,transparent_index:m,interlaced:!!I,delay:f,disposal:b});break;case 59:y=!1;break;default:throw new Error("Unknown gif block: 0x"+o[c-1].toString(16))}this.numFrames=function(){return l.length},this.loopCount=function(){return j},this.frameInfo=function(V){if(V<0||V>=l.length)throw new Error("Frame index out of range.");return l[V]},this.decodeAndBlitFrameBGRA=function(V,H){for(var V=this.frameInfo(V),K=V.width*V.height,ee=new Uint8Array(K),ue=(u(o,V.data_offset,ee,K),V.palette_offset),T=V.transparent_index,D=(T===null&&(T=256),V.width),G=g-D,W=D,$=4*(V.y*g+V.x),J=4*((V.y+V.height)*g+V.x),ne=$,ce=4*G,ie=(V.interlaced===!0&&(ce+=4*g*7),8),pe=0,Z=ee.length;pe>=1)),le===T?ne+=4:(z=o[ue+3*le],te=o[ue+3*le+1],le=o[ue+3*le+2],H[ne++]=le,H[ne++]=te,H[ne++]=z,H[ne++]=255),--W}},this.decodeAndBlitFrameRGBA=function(V,H){for(var V=this.frameInfo(V),K=V.width*V.height,ee=new Uint8Array(K),ue=(u(o,V.data_offset,ee,K),V.palette_offset),T=V.transparent_index,D=(T===null&&(T=256),V.width),G=g-D,W=D,$=4*(V.y*g+V.x),J=4*((V.y+V.height)*g+V.x),ne=$,ce=4*G,ie=(V.interlaced===!0&&(ce+=4*g*7),8),pe=0,Z=ee.length;pe>=1)),le===T?ne+=4:(z=o[ue+3*le],te=o[ue+3*le+1],le=o[ue+3*le+2],H[ne++]=z,H[ne++]=te,H[ne++]=le,H[ne++]=255),--W}}}}catch{}},{}],254:[function(t,x,v){(function(s){var u,o;u=this,o=function(c){function g(U){if(this==null)throw TypeError();var S,O=String(this),R=O.length,U=U?Number(U):0;if(!((U=U!=U?0:U)<0||R<=U))return 55296<=(S=O.charCodeAt(U))&&S<=56319&&U+1>>16-S;return _.tag>>>=S,_.bitcount-=S,R+O}function A(_,S){for(;_.bitcount<24;)_.tag|=_.source[_.sourceIndex++]<<_.bitcount,_.bitcount+=8;for(var O=0,R=0,U=0,X=_.tag;R=2*R+(1&X),X>>>=1,O+=S.table[++U],0<=(R-=S.table[U]););return _.tag=X,_.bitcount-=U,S.trans[O+R]}function N(_,S,O){for(;;){var R=A(_,S);if(R===256)return n;if(R<256)_.dest[_.destLen++]=R;else for(var U,X=I(_,f[R-=257],m[R]),R=A(_,O),Y=U=_.destLen-I(_,b[R],j[R]);Y>>=1,R=U,I(X,2,0)){case 0:O=function(Oe){for(var Je,ut;8this.x2&&(this.x2=_)),typeof S=="number"&&((isNaN(this.y1)||isNaN(this.y2))&&(this.y1=S,this.y2=S),Sthis.y2&&(this.y2=S))},K.prototype.addX=function(_){this.addPoint(_,null)},K.prototype.addY=function(_){this.addPoint(null,_)},K.prototype.addBezier=function(_,S,O,R,U,X,Y,oe){var he=[_,S],fe=[O,R],je=[U,X],ke=[Y,oe];this.addPoint(_,S),this.addPoint(Y,oe);for(var Te=0;Te<=1;Te++){var ve,Ue=6*he[Te]-12*fe[Te]+6*je[Te],Ae=-3*he[Te]+9*fe[Te]-9*je[Te]+3*ke[Te],Fe=3*fe[Te]-3*he[Te];Ae==0?Ue==0||0<(ve=-Fe/Ue)&&ve<1&&(Te===0&&this.addX(H(he[Te],fe[Te],je[Te],ke[Te],ve)),Te===1&&this.addY(H(he[Te],fe[Te],je[Te],ke[Te],ve))):(ve=Math.pow(Ue,2)-4*Fe*Ae)<0||(0<(Fe=(-Ue+Math.sqrt(ve))/(2*Ae))&&Fe<1&&(Te===0&&this.addX(H(he[Te],fe[Te],je[Te],ke[Te],Fe)),Te===1&&this.addY(H(he[Te],fe[Te],je[Te],ke[Te],Fe))),0<(Fe=(-Ue-Math.sqrt(ve))/(2*Ae))&&Fe<1&&(Te===0&&this.addX(H(he[Te],fe[Te],je[Te],ke[Te],Fe)),Te===1&&this.addY(H(he[Te],fe[Te],je[Te],ke[Te],Fe))))}},K.prototype.addQuad=function(_,S,O,R,U,X){O=_+2/3*(O-_),R=S+2/3*(R-S),this.addBezier(_,S,O,R,O+1/3*(U-_),R+1/3*(X-S),U,X)},ee.prototype.moveTo=function(_,S){this.commands.push({type:"M",x:_,y:S})},ee.prototype.lineTo=function(_,S){this.commands.push({type:"L",x:_,y:S})},ee.prototype.curveTo=ee.prototype.bezierCurveTo=function(_,S,O,R,U,X){this.commands.push({type:"C",x1:_,y1:S,x2:O,y2:R,x:U,y:X})},ee.prototype.quadTo=ee.prototype.quadraticCurveTo=function(_,S,O,R){this.commands.push({type:"Q",x1:_,y1:S,x:O,y:R})},ee.prototype.close=ee.prototype.closePath=function(){this.commands.push({type:"Z"})},ee.prototype.extend=function(_){var S;if(_.commands)_=_.commands;else if(_ instanceof K)return S=_,this.moveTo(S.x1,S.y1),this.lineTo(S.x2,S.y1),this.lineTo(S.x2,S.y2),this.lineTo(S.x1,S.y2),void this.close();Array.prototype.push.apply(this.commands,_)},ee.prototype.getBoundingBox=function(){for(var _=new K,S=0,O=0,R=0,U=0,X=0;X>8&255,255&_]},$.USHORT=J(2),W.SHORT=function(_){return[(_=32768<=_?-(65536-_):_)>>8&255,255&_]},$.SHORT=J(2),W.UINT24=function(_){return[_>>16&255,_>>8&255,255&_]},$.UINT24=J(3),W.ULONG=function(_){return[_>>24&255,_>>16&255,_>>8&255,255&_]},$.ULONG=J(4),W.LONG=function(_){return[(_=2147483648<=_?-(4294967296-_):_)>>24&255,_>>16&255,_>>8&255,255&_]},$.LONG=J(4),W.FIXED=W.ULONG,$.FIXED=$.ULONG,W.FWORD=W.SHORT,$.FWORD=$.SHORT,W.UFWORD=W.USHORT,$.UFWORD=$.USHORT,W.LONGDATETIME=function(_){return[0,0,0,0,_>>24&255,_>>16&255,_>>8&255,255&_]},$.LONGDATETIME=J(8),W.TAG=function(_){return D.argument(_.length===4,"Tag should be exactly 4 ASCII characters."),[_.charCodeAt(0),_.charCodeAt(1),_.charCodeAt(2),_.charCodeAt(3)]},$.TAG=J(4),W.Card8=W.BYTE,$.Card8=$.BYTE,W.Card16=W.USHORT,$.Card16=$.USHORT,W.OffSize=W.BYTE,$.OffSize=$.BYTE,W.SID=W.USHORT,$.SID=$.USHORT,W.NUMBER=function(_){return-107<=_&&_<=107?[_+139]:108<=_&&_<=1131?[247+((_-=108)>>8),255&_]:-1131<=_&&_<=-108?[251+((_=-_-108)>>8),255&_]:-32768<=_&&_<=32767?W.NUMBER16(_):W.NUMBER32(_)},$.NUMBER=function(_){return W.NUMBER(_).length},W.NUMBER16=function(_){return[28,_>>8&255,255&_]},$.NUMBER16=J(3),W.NUMBER32=function(_){return[29,_>>24&255,_>>16&255,_>>8&255,255&_]},$.NUMBER32=J(5),W.REAL=function(_){for(var S=_.toString(),O=/\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(S),R=(O&&(O=parseFloat("1e"+((O[2]?+O[2]:0)+O[1].length)),S=(Math.round(_*O)/O).toString()),""),U=0,X=S.length;U>8&255,S[S.length]=255&R}return S},$.UTF16=function(_){return 2*_.length};var ne,ce={"x-mac-croatian":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®Š™´¨≠ŽØ∞±≤≥∆µ∂∑∏š∫ªºΩžø¿¡¬√ƒ≈Ć«Č… ÀÃÕŒœĐ—“”‘’÷◊©⁄€‹›Æ»–·‚„‰ÂćÁčÈÍÎÏÌÓÔđÒÚÛÙıˆ˜¯πË˚¸Êæˇ","x-mac-cyrillic":"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ†°Ґ£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµґЈЄєЇїЉљЊњјЅ¬√ƒ≈∆«»… ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёяабвгдежзийклмнопрстуфхцчшщъыьэю","x-mac-gaelic":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØḂ±≤≥ḃĊċḊḋḞḟĠġṀæøṁṖṗɼƒſṠ«»… ÀÃÕŒœ–—“”‘’ṡẛÿŸṪ€‹›Ŷŷṫ·Ỳỳ⁊ÂÊÁËÈÍÎÏÌÓÔ♣ÒÚÛÙıÝýŴŵẄẅẀẁẂẃ","x-mac-greek":"Ĺ²É³ÖÜ΅àâä΄¨çéèê룙î‰ôö¦€ùûü†ΓΔΘΛΞΠß®©ΣΪ§≠°·Α±≤≥¥ΒΕΖΗΙΚΜΦΫΨΩάΝ¬ΟΡ≈Τ«»… ΥΧΆΈœ–―“”‘’÷ΉΊΌΎέήίόΏύαβψδεφγηιξκλμνοπώρστθωςχυζϊϋΐΰ­","x-mac-icelandic":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûüÝ°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€ÐðÞþý·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ","x-mac-inuit":"ᐃᐄᐅᐆᐊᐋᐱᐲᐳᐴᐸᐹᑉᑎᑏᑐᑑᑕᑖᑦᑭᑮᑯᑰᑲᑳᒃᒋᒌᒍᒎᒐᒑ°ᒡᒥᒦ•¶ᒧ®©™ᒨᒪᒫᒻᓂᓃᓄᓅᓇᓈᓐᓯᓰᓱᓲᓴᓵᔅᓕᓖᓗᓘᓚᓛᓪᔨᔩᔪᔫᔭ… ᔮᔾᕕᕖᕗ–—“”‘’ᕘᕙᕚᕝᕆᕇᕈᕉᕋᕌᕐᕿᖀᖁᖂᖃᖄᖅᖏᖐᖑᖒᖓᖔᖕᙱᙲᙳᙴᙵᙶᖖᖠᖡᖢᖣᖤᖥᖦᕼŁł","x-mac-ce":"ÄĀāÉĄÖÜáąČäčĆć鏟ĎíďĒēĖóėôöõúĚěü†°Ę£§•¶ß®©™ę¨≠ģĮįĪ≤≥īĶ∂∑łĻļĽľĹĺŅņѬ√ńŇ∆«»… ňŐÕőŌ–—“”‘’÷◊ōŔŕŘ‹›řŖŗŠ‚„šŚśÁŤťÍŽžŪÓÔūŮÚůŰűŲųÝýķŻŁżĢˇ",macintosh:"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ","x-mac-romanian":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ĂȘ∞±≤≥¥µ∂∑∏π∫ªºΩăș¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›Țț‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ","x-mac-turkish":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸĞğİıŞş‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙˆ˜¯˘˙˚¸˝˛ˇ"},ie=(G.MACSTRING=function(_,S,O,R){var U=ce[R];if(U!==void 0){for(var X="",Y=0;Y>8&255,Te+256&255)}return fe})(_,R,S);return S},W.INDEX=function(_){for(var S=1,O=[S],R=[],U=0;U<_.length;U+=1){var X=W.OBJECT(_[U]);Array.prototype.push.apply(R,X),S+=X.length,O.push(S)}if(R.length===0)return[0,0];for(var Y=[],oe=1+Math.floor(Math.log(S)/Math.log(2))/8|0,he=[void 0,W.BYTE,W.USHORT,W.UINT24,W.ULONG][oe],fe=0;fe>8,S[je+1]=255&ke,S=S.concat(R[fe])}return S},$.TABLE=function(_){for(var S=0,O=_.fields.length,R=0;R>1,oe.skip("uShort",3),Fe.glyphIndexMap={};for(var ut,et=new Ee.Parser(Ce,Oe+Je+14),tt=new Ee.Parser(Ce,Oe+Je+16+2*ut),ct=new Ee.Parser(Ce,Oe+Je+16+4*ut),kt=new Ee.Parser(Ce,Oe+Je+16+6*ut),Ut=Oe+Je+16+8*ut,qt=0;qt>4,Y=15&Y;if(X==15||(R+=U[X],Y==15))break;R+=U[Y]}return parseFloat(R)}if(32<=S&&S<=246)return S-139;if(247<=S&&S<=250)return 256*(S-247)+_.parseByte()+108;if(251<=S&&S<=254)return 256*-(S-251)-_.parseByte()-108;throw new Error("Invalid b0 "+S)}function ar(_,S,O){var R=new Ee.Parser(_,S=S!==void 0?S:0),U=[],X=[];for(O=O!==void 0?O:_.length;R.relativeOffset>1,ve.length=0,Ae=!0}return function tt(ct){for(var kt,Ut,qt,lr,ur,$r,Tt,At,wt,cr,Dt,or,Rt=0;RtMath.abs(or-Oe)?Ce=Dt+ve.shift():Oe=or+ve.shift(),Te.curveTo(R,U,X,Y,Tt,At),Te.curveTo(wt,cr,Dt,or,Ce,Oe);break;default:console.log("Glyph "+S.index+": unknown operator 1200"+er),ve.length=0}break;case 14:0>3;break;case 21:2>16),Rt+=2;break;case 29:ur=ve.pop()+_.gsubrsBias,($r=_.gsubrs[ur])&&tt($r);break;case 30:for(;0=O.begin&&_=xe.length&&(X=R.parseChar(),O.names.push(R.parseString(X)));break;case 2.5:O.numberOfGlyphs=R.parseUShort(),O.offset=new Array(O.numberOfGlyphs);for(var oe=0;oeke.value.tag?1:-1}),S.fields=S.fields.concat(R),S.fields=S.fields.concat(U),S}function Rl(_,S,O){for(var R=0;R 123 are reserved for internal usage");ve|=1<>>1,X=_[U].tag;if(X===S)return U;X>>1,X=_[U];if(X===S)return U;X>>1,Y=(U=_[X]).start;if(Y===S)return U;Y(U=_[O-1]).end?0:U}function gs(_,S){this.font=_,this.tableName=S}function vs(_){gs.call(this,_,"gpos")}function rn(_){gs.call(this,_,"gsub")}function Dl(_,S,O){for(var R=_.subtables,U=0;US.points.length-1||R.matchedPoints[1]>U.points.length-1)throw Error("Matched points out of range in "+S.name);var Y=S.points[R.matchedPoints[0]],oe=U.points[R.matchedPoints[1]],R={xScale:R.xScale,scale01:R.scale01,scale10:R.scale10,yScale:R.yScale,dx:0,dy:0},oe=Si([oe],R)[0];R.dx=Y.x-oe.x,R.dy=Y.y-oe.y,X=Si(U.points,R)}S.points=S.points.concat(X)}}return Ul(S.points)}(vs.prototype=gs.prototype={searchTag:ji,binSearch:Ll,getTable:function(_){var S=this.font.tables[this.tableName];return S=!S&&_?this.font.tables[this.tableName]=this.createDefaultTable():S},getScriptNames:function(){var _=this.getTable();return _?_.scripts.map(function(S){return S.tag}):[]},getDefaultScriptName:function(){var _=this.getTable();if(_){for(var S=!1,O=0;O<_.scripts.length;O++){var R=_.scripts[O].tag;if(R==="DFLT")return R;R==="latn"&&(S=!0)}return S?"latn":void 0}},getScriptTable:function(_,S){var O,R=this.getTable(S);if(R)return O=R.scripts,0<=(R=ji(R.scripts,_=_||"DFLT"))?O[R].script:S?(O.splice(-1-R,0,S={tag:_,script:{defaultLangSys:{reserved:0,reqFeatureIndex:65535,featureIndexes:[]},langSysRecords:[]}}),S.script):void 0},getLangSysTable:function(U,S,O){var R,U=this.getScriptTable(U,O);if(U)return S&&S!=="dflt"&&S!=="DFLT"?0<=(R=ji(U.langSysRecords,S))?U.langSysRecords[R].langSys:O?(U.langSysRecords.splice(-1-R,0,O={tag:S,langSys:{reserved:0,reqFeatureIndex:65535,featureIndexes:[]}}),O.langSys):void 0:U.defaultLangSys},getFeatureTable:function(_,S,O,R){if(_=this.getLangSysTable(_,S,R),_){for(var U,X=_.featureIndexes,Y=this.font.tables[this.tableName].features,oe=0;oe=Y[S-1].tag,"Features must be added in alphabetical order."),Y.push(U={tag:O,feature:{params:0,lookupListIndexes:[]}}),X.push(S),U.feature}},getLookupTables:function(X,S,O,R,U){var X=this.getFeatureTable(X,S,O,U),Y=[];if(X){for(var oe,he=X.lookupListIndexes,fe=this.font.tables[this.tableName].lookups,je=0;je",X),S.stack.push(Math.round(64*X))}function Ti(_,S){var O=S.stack,R=O.pop(),U=S.fv,X=S.pv,Y=S.ppem,oe=S.deltaBase+16*(_-1),he=S.deltaShift,fe=S.z0;c.DEBUG&&console.log(S.step,"DELTAP["+_+"]",R,O);for(var je=0;je>4)===Y&&(0<=(Te=(15&Te)-8)&&Te++,c.DEBUG&&console.log(S.step,"DELTAPFIX",ke,"by",Te*he),ke=fe[ke],U.setRelative(ke,ke,Te*he,X))}}function _s(_,S){var O=S.stack,R=O.pop();c.DEBUG&&console.log(S.step,"ROUND[]"),O.push(64*S.round(R/64))}function Mi(_,S){var O=S.stack,R=O.pop(),U=S.ppem,X=S.deltaBase+16*(_-1),Y=S.deltaShift;c.DEBUG&&console.log(S.step,"DELTAC["+_+"]",R,O);for(var oe=0;oe>4)===U&&(0<=(fe=(15&fe)-8)&&fe++,fe=fe*Y,c.DEBUG&&console.log(S.step,"DELTACFIX",he,"by",fe),S.cvt[he]+=fe)}}function su(_,S){var O,U=S.stack,R=U.pop(),U=U.pop(),X=S.z2[R],Y=S.z1[U];c.DEBUG&&console.log(S.step,"SDPVTL["+_+"]",R,U),R=_?(O=X.y-Y.y,Y.x-X.x):(O=Y.x-X.x,Y.y-X.y),S.dpv=Ao(O,R)}function bn(_,S){var O=S.stack,R=S.prog,U=S.ip;c.DEBUG&&console.log(S.step,"PUSHB["+_+"]");for(var X=0;X<_;X++)O.push(R[++U]);S.ip=U}function _n(_,S){var O=S.ip,R=S.prog,U=S.stack;c.DEBUG&&console.log(S.ip,"PUSHW["+_+"]");for(var X=0;X<_;X++){var Y=R[++O]<<8|R[++O];32768&Y&&(Y=-(1+(65535^Y))),U.push(Y)}S.ip=O}function Qe(_,S,O,R,U,X){var Y,oe,fe=X.stack,he=_&&fe.pop(),fe=fe.pop(),je=X.rp0,je=X.z0[je],ke=X.z1[fe],Te=X.minDis,ve=X.fv,Ue=X.dpv,Ae=Y=Ue.distance(ke,je,!0,!0),Fe=0<=Ae?1:-1;Ae=Math.abs(Ae),_&&(oe=X.cvt[he],R&&Math.abs(Ae-oe)":"_")+(R?"R":"_")+(U===0?"Gr":U===1?"Bl":U===2?"Wh":"")+"]",_?he+"("+X.cvt[he]+","+oe+")":"",fe,"(d =",Y,"->",Fe*Ae,")"),X.rp1=X.rp0,X.rp2=fe,S&&(X.rp0=fe)}Gl.prototype.exec=function(_,S){if(typeof S!="number")throw new Error("Point size is not a number!");if(!(2",R),oe.interpolate(ke,X,Y,he),oe.touch(ke)}_.loop=1},tu.bind(void 0,0),tu.bind(void 0,1),function(_){for(var S=_.stack,O=_.rp0,R=_.z0[O],U=_.loop,X=_.fv,Y=_.pv,oe=_.z1;U--;){var he=S.pop(),fe=oe[he];c.DEBUG&&console.log(_.step,(1<_.loop?"loop "+(_.loop-U)+": ":"")+"ALIGNRP[]",he),X.setRelative(fe,R,0,Y),X.touch(fe)}_.loop=1},function(_){c.DEBUG&&console.log(_.step,"RTDG[]"),_.round=vh},ru.bind(void 0,0),ru.bind(void 0,1),function(_){var S=_.prog,O=_.ip,R=_.stack,U=S[++O];c.DEBUG&&console.log(_.step,"NPUSHB[]",U);for(var X=0;X"u"?Ph:Ah)(_,function(O,R){if(O)return S(O);var U;try{U=ki(R)}catch(X){return S(X,null)}return S(null,U)})},c.loadSync=function(_){return ki(Fl(t("fs").readFileSync(_)))},Object.defineProperty(c,"__esModule",{value:!0})},o(typeof v=="object"&&x!==void 0?v:u.opentype={})}).call(this,t("buffer").Buffer)},{buffer:4,fs:2}],255:[function(t,x,v){(function(s){function u(g,p){for(var n=0,i=g.length-1;0<=i;i--){var a=g[i];a==="."?g.splice(i,1):a===".."?(g.splice(i,1),n++):n&&(g.splice(i,1),n--)}if(p)for(;n--;)g.unshift("..");return g}function o(g,p){if(g.filter)return g.filter(p);for(var n=[],i=0;i'.concat(f,"").concat(h,""),this.dummyDOM||(this.dummyDOM=document.getElementById(l).parentNode),this.descriptions?this.descriptions.fallbackElements||(this.descriptions.fallbackElements={}):this.descriptions={fallbackElements:{}},this.descriptions.fallbackElements[a]?this.descriptions.fallbackElements[a].innerHTML!==f&&(this.descriptions.fallbackElements[a].innerHTML=f):this._describeElementHTML("fallback",a,f),y===this.LABEL&&(this.descriptions.labelElements||(this.descriptions.labelElements={}),this.descriptions.labelElements[a]?this.descriptions.labelElements[a].innerHTML!==f&&(this.descriptions.labelElements[a].innerHTML=f):this._describeElementHTML("label",a,f)))},s.default.prototype._describeHTML=function(a,h){var y,l=this.canvas.id;a==="fallback"?(this.dummyDOM.querySelector("#".concat(l+u))?this.dummyDOM.querySelector("#"+l+c).insertAdjacentHTML("beforebegin",'

        ')):(y='

        '),this.dummyDOM.querySelector("#".concat(l,"accessibleOutput"))?this.dummyDOM.querySelector("#".concat(l,"accessibleOutput")).insertAdjacentHTML("beforebegin",y):this.dummyDOM.querySelector("#".concat(l)).innerHTML=y),this.descriptions.fallback=this.dummyDOM.querySelector("#".concat(l).concat(o)),this.descriptions.fallback.innerHTML=h):a==="label"&&(this.dummyDOM.querySelector("#".concat(l+g))?this.dummyDOM.querySelector("#".concat(l+n))&&this.dummyDOM.querySelector("#".concat(l+n)).insertAdjacentHTML("beforebegin",'

        ')):(y='

        '),this.dummyDOM.querySelector("#".concat(l,"accessibleOutputLabel"))?this.dummyDOM.querySelector("#".concat(l,"accessibleOutputLabel")).insertAdjacentHTML("beforebegin",y):this.dummyDOM.querySelector("#"+l).insertAdjacentHTML("afterend",y)),this.descriptions.label=this.dummyDOM.querySelector("#"+l+p),this.descriptions.label.innerHTML=h)},s.default.prototype._describeElementHTML=function(a,h,y){var l,f=this.canvas.id;a==="fallback"?(this.dummyDOM.querySelector("#".concat(f+u))?this.dummyDOM.querySelector("#"+f+c)||this.dummyDOM.querySelector("#"+f+o).insertAdjacentHTML("afterend",'
        Canvas elements and their descriptions
        ')):(l='
        Canvas elements and their descriptions
        '),this.dummyDOM.querySelector("#".concat(f,"accessibleOutput"))?this.dummyDOM.querySelector("#".concat(f,"accessibleOutput")).insertAdjacentHTML("beforebegin",l):this.dummyDOM.querySelector("#"+f).innerHTML=l),(l=document.createElement("tr")).id=f+"_fte_"+h,this.dummyDOM.querySelector("#"+f+c).appendChild(l),this.descriptions.fallbackElements[h]=this.dummyDOM.querySelector("#".concat(f).concat("_fte_").concat(h)),this.descriptions.fallbackElements[h].innerHTML=y):a==="label"&&(this.dummyDOM.querySelector("#".concat(f+g))?this.dummyDOM.querySelector("#".concat(f+n))||this.dummyDOM.querySelector("#"+f+p).insertAdjacentHTML("afterend",'
        ')):(l='
        '),this.dummyDOM.querySelector("#".concat(f,"accessibleOutputLabel"))?this.dummyDOM.querySelector("#".concat(f,"accessibleOutputLabel")).insertAdjacentHTML("beforebegin",l):this.dummyDOM.querySelector("#"+f).insertAdjacentHTML("afterend",l)),(a=document.createElement("tr")).id=f+"_lte_"+h,this.dummyDOM.querySelector("#"+f+n).appendChild(a),this.descriptions.labelElements[h]=this.dummyDOM.querySelector("#".concat(f).concat("_lte_").concat(h)),this.descriptions.labelElements[h].innerHTML=y)},t=s.default,v.default=t},{"../core/main":280,"core-js/modules/es.array.concat":152,"core-js/modules/es.regexp.exec":192,"core-js/modules/es.string.ends-with":195,"core-js/modules/es.string.replace":201}],261:[function(t,x,v){t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.from"),t("core-js/modules/es.array.map"),t("core-js/modules/es.string.iterator"),t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.from"),t("core-js/modules/es.array.map"),t("core-js/modules/es.string.iterator"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0,t=(t=t("../core/main"))&&t.__esModule?t:{default:t},t.default.prototype._updateGridOutput=function(s){var u,o,c,g;this.dummyDOM.querySelector("#".concat(s,"_summary"))&&(u=this._accessibleOutputs[s],c=function(p,n,i,a){return n="".concat(n," canvas, ").concat(i," by ").concat(a," pixels, contains ").concat(p[0]),n=(p[0]===1?"".concat(n," shape: "):"".concat(n," shapes: ")).concat(p[1]),n}((o=function(p,n){var i,a="",h="",y=0;for(i in n){var l,f=0;for(l in n[i]){var m='
      • ').concat(n[i][l].color," ").concat(i,",");i==="line"?m+=" location = ".concat(n[i][l].pos,", length = ").concat(n[i][l].length," pixels"):(m+=" location = ".concat(n[i][l].pos),i!=="point"&&(m+=", area = ".concat(n[i][l].area," %")),m+="
      • "),a+=m,f++,y++}h=1').concat(n[i][f].color," ").concat(i,"
        "):'').concat(n[i][f].color," ").concat(i," midpoint"),l[n[i][f].loc.locY][n[i][f].loc.locX]?l[n[i][f].loc.locY][n[i][f].loc.locX]=l[n[i][f].loc.locY][n[i][f].loc.locX]+" "+m:l[n[i][f].loc.locY][n[i][f].loc.locX]=m,h++}for(a in l){var b,j="";for(b in l[a])j+="",l[a][b]!==void 0&&(j+=l[a][b]),j+="";y=y+j+""}return y}(s,this.ingredients.shapes),c!==u.summary.innerHTML&&(u.summary.innerHTML=c),g!==u.map.innerHTML&&(u.map.innerHTML=g),o.details!==u.shapeDetails.innerHTML&&(u.shapeDetails.innerHTML=o.details),this._accessibleOutputs[s]=u)},t=t.default,v.default=t},{"../core/main":280,"core-js/modules/es.array.concat":152,"core-js/modules/es.array.from":161,"core-js/modules/es.array.map":167,"core-js/modules/es.string.iterator":197}],262:[function(t,x,v){t("core-js/modules/es.symbol"),t("core-js/modules/es.symbol.description"),t("core-js/modules/es.symbol.iterator"),t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.fill"),t("core-js/modules/es.array.from"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.map"),t("core-js/modules/es.number.to-fixed"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.regexp.to-string"),t("core-js/modules/es.string.iterator"),t("core-js/modules/web.dom-collections.iterator"),t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.fill"),t("core-js/modules/es.array.map"),t("core-js/modules/es.number.to-fixed"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0;var s=(t=t("../core/main"))&&t.__esModule?t:{default:t};function u(c){return function(g){if(Array.isArray(g)){for(var p=0,n=new Array(g.length);p')):this.dummyDOM.querySelector("#".concat(a)).innerHTML='
        '))):g==="Label"&&(p=a+c+(h=g),this.dummyDOM.querySelector("#".concat(n=a+"accessibleOutput"+g))||(this.dummyDOM.querySelector("#".concat(a,"_Label"))?this.dummyDOM.querySelector("#".concat(a,"_Label")):this.dummyDOM.querySelector("#".concat(a))).insertAdjacentHTML("afterend",'
        '))),this._accessibleOutputs[p]={},c==="textOutput"?(h="#".concat(a,"gridOutput").concat(h),i='
        Text Output

          '),this.dummyDOM.querySelector(h)?this.dummyDOM.querySelector(h).insertAdjacentHTML("beforebegin",i):this.dummyDOM.querySelector("#".concat(n)).innerHTML=i,this._accessibleOutputs[p].list=this.dummyDOM.querySelector("#".concat(p,"_list"))):c==="gridOutput"&&(h="#".concat(a,"textOutput").concat(h),i='
          Grid Output

            '),this.dummyDOM.querySelector(h)?this.dummyDOM.querySelector(h).insertAdjacentHTML("afterend",i):this.dummyDOM.querySelector("#".concat(n)).innerHTML=i,this._accessibleOutputs[p].map=this.dummyDOM.querySelector("#".concat(p,"_map"))),this._accessibleOutputs[p].shapeDetails=this.dummyDOM.querySelector("#".concat(p,"_shapeDetails")),this._accessibleOutputs[p].summary=this.dummyDOM.querySelector("#".concat(p,"_summary"))},s.default.prototype._updateAccsOutput=function(){var c=this.canvas.id;JSON.stringify(this.ingredients.shapes)===this.ingredients.pShapes&&this.ingredients.colors.background===this.ingredients.pBackground||(this.ingredients.pShapes=JSON.stringify(this.ingredients.shapes),this._accessibleOutputs.text&&this._updateTextOutput(c+"textOutput"),this._accessibleOutputs.grid&&this._updateGridOutput(c+"gridOutput"),this._accessibleOutputs.textLabel&&this._updateTextOutput(c+"textOutputLabel"),this._accessibleOutputs.gridLabel&&this._updateGridOutput(c+"gridOutputLabel"))},s.default.prototype._accsBackground=function(c){this.ingredients.pShapes=JSON.stringify(this.ingredients.shapes),this.ingredients.pBackground=this.ingredients.colors.background,this.ingredients.shapes={},this.ingredients.colors.backgroundRGBA!==c&&(this.ingredients.colors.backgroundRGBA=c,this.ingredients.colors.background=this._rgbColorName(c))},s.default.prototype._accsCanvasColors=function(c,g){c==="fill"?this.ingredients.colors.fillRGBA!==g&&(this.ingredients.colors.fillRGBA=g,this.ingredients.colors.fill=this._rgbColorName(g)):c==="stroke"&&this.ingredients.colors.strokeRGBA!==g&&(this.ingredients.colors.strokeRGBA=g,this.ingredients.colors.stroke=this._rgbColorName(g))},s.default.prototype._accsOutput=function(c,g){c==="ellipse"&&g[2]===g[3]?c="circle":c==="rectangle"&&g[2]===g[3]&&(c="square");var p,n,i={},a=!0,h=function(l,f){var m;return l=l==="rectangle"||l==="ellipse"||l==="arc"||l==="circle"||l==="square"?(m=Math.round(f[0]+f[2]/2),Math.round(f[1]+f[3]/2)):l==="triangle"?(m=(f[0]+f[2]+f[4])/3,(f[1]+f[3]+f[5])/3):l==="quadrilateral"?(m=(f[0]+f[2]+f[4]+f[6])/4,(f[1]+f[3]+f[5]+f[7])/4):l==="line"?(m=(f[0]+f[2])/2,(f[1]+f[3])/2):(m=f[0],f[1]),[m,l]}(c,g);if(c==="line"?(i.color=this.ingredients.colors.stroke,i.length=Math.round(this.dist(g[0],g[1],g[2],g[3])),p=this._getPos(g[0],[1]),n=this._getPos(g[2],[3]),i.loc=o(h,this.width,this.height),i.pos=p===n?"at ".concat(p):"from ".concat(p," to ").concat(n)):(c==="point"?i.color=this.ingredients.colors.stroke:(i.color=this.ingredients.colors.fill,i.area=this._getArea(c,g)),i.pos=this._getPos.apply(this,u(h)),i.loc=o(h,this.width,this.height)),this.ingredients.shapes[c]){if(this.ingredients.shapes[c]!==[i]){for(var y in this.ingredients.shapes[c])JSON.stringify(this.ingredients.shapes[c][y])===JSON.stringify(i)&&(a=!1);a===!0&&this.ingredients.shapes[c].push(i)}}else this.ingredients.shapes[c]=[i]},s.default.prototype._getPos=function(n,p){var n=new DOMPointReadOnly(n,p),p=this._renderer.isP3D?new DOMMatrix(this._renderer.uMVMatrix.mat4):this.drawingContext.getTransform(),n=n.matrixTransform(p),p=n.x,n=n.y,i=this.width*this._pixelDensity,a=this.height*this._pixelDensity;return p<.4*i?n<.4*a?"top left":.6*aMath.PI?i+=n:i-=n)):c==="ellipse"||c==="circle"?i=3.14*g[2]/2*g[3]/2:c==="line"||c==="point"?i=0:c==="quadrilateral"?i=Math.abs((g[6]+g[0])*(g[7]-g[1])+(g[0]+g[2])*(g[1]-g[3])+(g[2]+g[4])*(g[3]-g[5])+(g[4]+g[6])*(g[5]-g[7]))/2:c==="rectangle"||c==="square"?i=g[2]*g[3]:c==="triangle"&&(i=Math.abs(g[0]*(g[3]-g[5])+g[2]*(g[5]-g[1])+g[4]*(g[1]-g[3]))/2),this.width*this._pixelDensity),h=this.height*this._pixelDensity,y=[new DOMPoint(0,0),new DOMPoint(a,0),new DOMPoint(a,h),new DOMPoint(0,h)],l=(this._renderer.isP3D?new DOMMatrix(this._renderer.uMVMatrix.mat4):this.drawingContext.getTransform()).inverse(),f=y.map(function(b){return b.matrixTransform(l)}),m=Math.abs((f[3].x+f[0].x)*(f[3].y-f[0].y)+(f[0].x+f[1].x)*(f[0].y-f[1].y)+(f[1].x+f[2].x)*(f[1].y-f[2].y)+(f[2].x+f[3].x)*(f[2].y-f[3].y))/2;return Math.round(100*i/m)},t=s.default,v.default=t},{"../core/main":280,"core-js/modules/es.array.concat":152,"core-js/modules/es.array.fill":155,"core-js/modules/es.array.from":161,"core-js/modules/es.array.iterator":164,"core-js/modules/es.array.map":167,"core-js/modules/es.number.to-fixed":180,"core-js/modules/es.object.to-string":187,"core-js/modules/es.regexp.to-string":193,"core-js/modules/es.string.iterator":197,"core-js/modules/es.symbol":209,"core-js/modules/es.symbol.description":207,"core-js/modules/es.symbol.iterator":208,"core-js/modules/web.dom-collections.iterator":243}],263:[function(t,x,v){t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.concat"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0,t=(t=t("../core/main"))&&t.__esModule?t:{default:t},t.default.prototype._updateTextOutput=function(s){var u,o,c,g;this.dummyDOM.querySelector("#".concat(s,"_summary"))&&(u=this._accessibleOutputs[s],c=function(p,n,i,a){return i="Your output is a, ".concat(i," by ").concat(a," pixels, ").concat(n," canvas containing the following"),i=p===1?"".concat(i," shape:"):"".concat(i," ").concat(p," shapes:"),i}((o=function(p,n){var i,a="",h=0;for(i in n)for(var y in n[i]){var l='
          • ').concat(n[i][y].color," ").concat(i,"");i==="line"?l+=", ".concat(n[i][y].pos,", ").concat(n[i][y].length," pixels long.
          • "):(l+=", at ".concat(n[i][y].pos),i!=="point"&&(l+=", covering ".concat(n[i][y].area,"% of the canvas")),l+="."),a+=l,h++}return{numShapes:h,listShapes:a}}(s,this.ingredients.shapes)).numShapes,this.ingredients.colors.background,this.width,this.height),g=function(p,n){var i,a="",h=0;for(i in n)for(var y in n[i]){var l='').concat(n[i][y].color," ").concat(i,"");i==="line"?l+="location = ".concat(n[i][y].pos,"length = ").concat(n[i][y].length," pixels"):(l+="location = ".concat(n[i][y].pos,""),i!=="point"&&(l+=" area = ".concat(n[i][y].area,"%")),l+=""),a+=l,h++}return a}(s,this.ingredients.shapes),c!==u.summary.innerHTML&&(u.summary.innerHTML=c),o.listShapes!==u.list.innerHTML&&(u.list.innerHTML=o.listShapes),g!==u.shapeDetails.innerHTML&&(u.shapeDetails.innerHTML=g),this._accessibleOutputs[s]=u)},t=t.default,v.default=t},{"../core/main":280,"core-js/modules/es.array.concat":152}],264:[function(t,x,v){var s=(s=t("./core/main"))&&s.__esModule?s:{default:s};t("./core/constants"),t("./core/environment"),t("./core/friendly_errors/stacktrace"),t("./core/friendly_errors/validate_params"),t("./core/friendly_errors/file_errors"),t("./core/friendly_errors/fes_core"),t("./core/friendly_errors/sketch_reader"),t("./core/helpers"),t("./core/legacy"),t("./core/preload"),t("./core/p5.Element"),t("./core/p5.Graphics"),t("./core/p5.Renderer"),t("./core/p5.Renderer2D"),t("./core/rendering"),t("./core/shim"),t("./core/structure"),t("./core/transform"),t("./core/shape/2d_primitives"),t("./core/shape/attributes"),t("./core/shape/curves"),t("./core/shape/vertex"),t("./accessibility/outputs"),t("./accessibility/textOutput"),t("./accessibility/gridOutput"),t("./accessibility/color_namer"),t("./color/color_conversion"),t("./color/creating_reading"),t("./color/p5.Color"),t("./color/setting"),t("./data/p5.TypedDict"),t("./data/local_storage.js"),t("./dom/dom"),t("./accessibility/describe"),t("./events/acceleration"),t("./events/keyboard"),t("./events/mouse"),t("./events/touch"),t("./image/filters"),t("./image/image"),t("./image/loading_displaying"),t("./image/p5.Image"),t("./image/pixels"),t("./io/files"),t("./io/p5.Table"),t("./io/p5.TableRow"),t("./io/p5.XML"),t("./math/calculation"),t("./math/math"),t("./math/noise"),t("./math/p5.Vector"),t("./math/random"),t("./math/trigonometry"),t("./typography/attributes"),t("./typography/loading_displaying"),t("./typography/p5.Font"),t("./utilities/array_functions"),t("./utilities/conversion"),t("./utilities/string_functions"),t("./utilities/time_date"),t("./webgl/3d_primitives"),t("./webgl/interaction"),t("./webgl/light"),t("./webgl/loading"),t("./webgl/material"),t("./webgl/p5.Camera"),t("./webgl/p5.DataArray"),t("./webgl/p5.Geometry"),t("./webgl/p5.Matrix"),t("./webgl/p5.RendererGL.Immediate"),t("./webgl/p5.RendererGL"),t("./webgl/p5.RendererGL.Retained"),t("./webgl/p5.Framebuffer"),t("./webgl/p5.Shader"),t("./webgl/p5.RenderBuffer"),t("./webgl/p5.Texture"),t("./webgl/text"),t("./core/init"),x.exports=s.default},{"./accessibility/color_namer":259,"./accessibility/describe":260,"./accessibility/gridOutput":261,"./accessibility/outputs":262,"./accessibility/textOutput":263,"./color/color_conversion":265,"./color/creating_reading":266,"./color/p5.Color":267,"./color/setting":268,"./core/constants":269,"./core/environment":270,"./core/friendly_errors/fes_core":271,"./core/friendly_errors/file_errors":272,"./core/friendly_errors/sketch_reader":273,"./core/friendly_errors/stacktrace":274,"./core/friendly_errors/validate_params":275,"./core/helpers":276,"./core/init":277,"./core/legacy":279,"./core/main":280,"./core/p5.Element":281,"./core/p5.Graphics":282,"./core/p5.Renderer":283,"./core/p5.Renderer2D":284,"./core/preload":285,"./core/rendering":286,"./core/shape/2d_primitives":287,"./core/shape/attributes":288,"./core/shape/curves":289,"./core/shape/vertex":290,"./core/shim":291,"./core/structure":292,"./core/transform":293,"./data/local_storage.js":294,"./data/p5.TypedDict":295,"./dom/dom":296,"./events/acceleration":297,"./events/keyboard":298,"./events/mouse":299,"./events/touch":300,"./image/filters":301,"./image/image":302,"./image/loading_displaying":303,"./image/p5.Image":304,"./image/pixels":305,"./io/files":306,"./io/p5.Table":307,"./io/p5.TableRow":308,"./io/p5.XML":309,"./math/calculation":310,"./math/math":311,"./math/noise":312,"./math/p5.Vector":313,"./math/random":314,"./math/trigonometry":315,"./typography/attributes":316,"./typography/loading_displaying":317,"./typography/p5.Font":318,"./utilities/array_functions":319,"./utilities/conversion":320,"./utilities/string_functions":321,"./utilities/time_date":322,"./webgl/3d_primitives":323,"./webgl/interaction":325,"./webgl/light":326,"./webgl/loading":327,"./webgl/material":328,"./webgl/p5.Camera":329,"./webgl/p5.DataArray":330,"./webgl/p5.Framebuffer":331,"./webgl/p5.Geometry":332,"./webgl/p5.Matrix":333,"./webgl/p5.RenderBuffer":334,"./webgl/p5.RendererGL":337,"./webgl/p5.RendererGL.Immediate":335,"./webgl/p5.RendererGL.Retained":336,"./webgl/p5.Shader":338,"./webgl/p5.Texture":339,"./webgl/text":340}],265:[function(t,x,v){Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0,t=(t=t("../core/main"))&&t.__esModule?t:{default:t},t.default.ColorConversion={_hsbaToHSLA:function(s){var u=s[0],o=s[1],c=s[2],g=(2-o)*c/2;return g!=0&&(g==1?o=0:g<.5?o/=2-o:o=o*c/(2-2*g)),[u,o,g,s[3]]},_hsbaToRGBA:function(s){var u,o,c,g,p,n=6*s[0],i=s[1],a=s[2];return i===0?[a,a,a,s[3]]:(o=a*(1-i),c=a*(1-i*(n-(u=Math.floor(n)))),i=a*(1-i*(1+u-n)),n=u===1?(g=c,p=a,o):u===2?(g=o,p=a,i):u===3?(g=o,p=c,a):u===4?(g=i,p=o,a):u===5?(g=a,p=o,c):(g=a,p=i,o),[g,p,n,s[3]])},_hslaToHSBA:function(s){var u=s[0],o=s[1],c=s[2],g=c<.5?(1+o)*c:c+o-c*o;return[u,o=2*(g-c)/g,g,s[3]]},_hslaToRGBA:function(s){var u,o=6*s[0],c=s[1],g=s[2];return c===0?[g,g,g,s[3]]:[(u=function(p,n,i){return p<0?p+=6:6<=p&&(p-=6),p<1?n+(i-n)*p:p<3?i:p<4?n+(i-n)*(4-p):n})(2+o,c=2*g-(g=g<.5?(1+c)*g:g+c-g*c),g),u(o,c,g),u(o-2,c,g),s[3]]},_rgbaToHSBA:function(s){var u,o,c=s[0],g=s[1],p=s[2],n=Math.max(c,g,p),i=n-Math.min(c,g,p);return i==0?o=u=0:(o=i/n,c===n?u=(g-p)/i:g===n?u=2+(p-c)/i:p===n&&(u=4+(c-g)/i),u<0?u+=6:6<=u&&(u-=6)),[u/6,o,n,s[3]]},_rgbaToHSLA:function(s){var u,o,c=s[0],g=s[1],p=s[2],n=Math.max(c,g,p),a=Math.min(c,g,p),i=n+a,a=n-a;return a==0?o=u=0:(o=i<1?a/i:a/(2-i),c===n?u=(g-p)/a:g===n?u=2+(p-c)/a:p===n&&(u=4+(c-g)/a),u<0?u+=6:6<=u&&(u-=6)),[u/6,o,i/2,s[3]]}},t=t.default.ColorConversion,v.default=t},{"../core/main":280}],266:[function(t,x,v){function s(n){return(s=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(i){return typeof i}:function(i){return i&&typeof Symbol=="function"&&i.constructor===Symbol&&i!==Symbol.prototype?"symbol":typeof i})(n)}function u(n){return(u=typeof Symbol=="function"&&s(Symbol.iterator)==="symbol"?function(i){return s(i)}:function(i){return i&&typeof Symbol=="function"&&i.constructor===Symbol&&i!==Symbol.prototype?"symbol":s(i)})(n)}t("core-js/modules/es.symbol"),t("core-js/modules/es.symbol.description"),t("core-js/modules/es.symbol.iterator"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.map"),t("core-js/modules/es.object.get-own-property-descriptor"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.string.iterator"),t("core-js/modules/es.weak-map"),t("core-js/modules/web.dom-collections.iterator"),t("core-js/modules/es.array.map"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0;var o=(p=t("../core/main"))&&p.__esModule?p:{default:p},c=function(n){if(n&&n.__esModule)return n;if(n===null||u(n)!=="object"&&typeof n!="function")return{default:n};var i=g();if(i&&i.has(n))return i.get(n);var a,h={},y=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(a in n){var l;Object.prototype.hasOwnProperty.call(n,a)&&((l=y?Object.getOwnPropertyDescriptor(n,a):null)&&(l.get||l.set)?Object.defineProperty(h,a,l):h[a]=n[a])}return h.default=n,i&&i.set(n,h),h}(t("../core/constants"));function g(){var n;return typeof WeakMap!="function"?null:(n=new WeakMap,g=function(){return n},n)}t("./p5.Color"),t("../core/friendly_errors/validate_params"),t("../core/friendly_errors/file_errors"),t("../core/friendly_errors/fes_core"),o.default.prototype.alpha=function(n){return o.default._validateParameters("alpha",arguments),this.color(n)._getAlpha()},o.default.prototype.blue=function(n){return o.default._validateParameters("blue",arguments),this.color(n)._getBlue()},o.default.prototype.brightness=function(n){return o.default._validateParameters("brightness",arguments),this.color(n)._getBrightness()},o.default.prototype.color=function(){for(var n,i=arguments.length,a=new Array(i),h=0;hl[0]?l[0]+=1:y[0]+=1),1<=(h=this.lerp(y[0],l[0],a))&&--h),n=this.lerp(y[1],l[1],a),i=this.lerp(y[2],l[2],a),y=this.lerp(y[3],l[3],a),h*=m[f][0],n*=m[f][1],i*=m[f][2],y*=m[f][3],this.color(h,n,i,y)},o.default.prototype.lightness=function(n){return o.default._validateParameters("lightness",arguments),this.color(n)._getLightness()},o.default.prototype.red=function(n){return o.default._validateParameters("red",arguments),this.color(n)._getRed()},o.default.prototype.saturation=function(n){return o.default._validateParameters("saturation",arguments),this.color(n)._getSaturation()};var p=o.default;v.default=p},{"../core/constants":269,"../core/friendly_errors/fes_core":271,"../core/friendly_errors/file_errors":272,"../core/friendly_errors/validate_params":275,"../core/main":280,"./p5.Color":267,"core-js/modules/es.array.iterator":164,"core-js/modules/es.array.map":167,"core-js/modules/es.object.get-own-property-descriptor":183,"core-js/modules/es.object.to-string":187,"core-js/modules/es.string.iterator":197,"core-js/modules/es.symbol":209,"core-js/modules/es.symbol.description":207,"core-js/modules/es.symbol.iterator":208,"core-js/modules/es.weak-map":241,"core-js/modules/web.dom-collections.iterator":243}],267:[function(h,x,v){function s(b){return(s=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(j){return typeof j}:function(j){return j&&typeof Symbol=="function"&&j.constructor===Symbol&&j!==Symbol.prototype?"symbol":typeof j})(b)}function u(b){return(u=typeof Symbol=="function"&&s(Symbol.iterator)==="symbol"?function(j){return s(j)}:function(j){return j&&typeof Symbol=="function"&&j.constructor===Symbol&&j!==Symbol.prototype?"symbol":s(j)})(b)}h("core-js/modules/es.symbol"),h("core-js/modules/es.symbol.description"),h("core-js/modules/es.symbol.iterator"),h("core-js/modules/es.array.includes"),h("core-js/modules/es.array.iterator"),h("core-js/modules/es.array.join"),h("core-js/modules/es.array.map"),h("core-js/modules/es.array.slice"),h("core-js/modules/es.object.get-own-property-descriptor"),h("core-js/modules/es.object.to-string"),h("core-js/modules/es.regexp.constructor"),h("core-js/modules/es.regexp.exec"),h("core-js/modules/es.regexp.to-string"),h("core-js/modules/es.string.includes"),h("core-js/modules/es.string.iterator"),h("core-js/modules/es.string.trim"),h("core-js/modules/es.weak-map"),h("core-js/modules/web.dom-collections.iterator"),h("core-js/modules/es.array.includes"),h("core-js/modules/es.array.join"),h("core-js/modules/es.array.map"),h("core-js/modules/es.array.slice"),h("core-js/modules/es.object.to-string"),h("core-js/modules/es.regexp.constructor"),h("core-js/modules/es.regexp.exec"),h("core-js/modules/es.regexp.to-string"),h("core-js/modules/es.string.includes"),h("core-js/modules/es.string.trim"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0;var o=n(h("../core/main")),c=function(b){if(b&&b.__esModule)return b;if(b===null||u(b)!=="object"&&typeof b!="function")return{default:b};var j=p();if(j&&j.has(b))return j.get(b);var M,E={},k=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(M in b){var P;Object.prototype.hasOwnProperty.call(b,M)&&((P=k?Object.getOwnPropertyDescriptor(b,M):null)&&(P.get||P.set)?Object.defineProperty(E,M,P):E[M]=b[M])}return E.default=b,j&&j.set(b,E),E}(h("../core/constants")),g=n(h("./color_conversion"));function p(){var b;return typeof WeakMap!="function"?null:(b=new WeakMap,p=function(){return b},b)}function n(b){return b&&b.__esModule?b:{default:b}}function i(b,j){for(var M=0;M"].indexOf(i[0])?void 0:i[0],lineNumber:i[1],columnNumber:i[2],source:p}},this)},parseFFOrSafari:function(g){return g.stack.split(` +`).filter(function(p){return!p.match(c)},this).map(function(p){var n,i;return(p=-1 eval")?p.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,":$1"):p).indexOf("@")===-1&&p.indexOf(":")===-1?{functionName:p}:{functionName:(i=p.match(n=/((.*".+"[^@]*)?[^@]*)(?:@)/))&&i[1]?i[1]:void 0,fileName:(i=this.extractLocation(p.replace(n,"")))[0],lineNumber:i[1],columnNumber:i[2],source:p}},this)},parseOpera:function(g){return!g.stacktrace||-1g.stacktrace.split(` +`).length?this.parseOpera9(g):g.stack?this.parseOpera11(g):this.parseOpera10(g)},parseOpera9:function(g){for(var p=/Line (\d+).*script (?:in )?(\S+)/i,n=g.message.split(` +`),i=[],a=2,h=n.length;a/,"$2").replace(/\([^)]*\)/g,"")||void 0,args:(n=a.match(/\(([^)]*)\)/)?a.replace(/^[^(]+\(([^)]*)\)$/,"$1"):n)===void 0||n==="[arguments not available]"?void 0:n.split(","),fileName:i[0],lineNumber:i[1],columnNumber:i[2],source:p}},this)}}}t.default._getErrorStackParser=function(){return new s},t=t.default,v.default=t},{"../main":280,"core-js/modules/es.array.filter":156,"core-js/modules/es.array.index-of":163,"core-js/modules/es.array.join":165,"core-js/modules/es.array.map":167,"core-js/modules/es.array.slice":168,"core-js/modules/es.regexp.exec":192,"core-js/modules/es.string.match":198,"core-js/modules/es.string.replace":201,"core-js/modules/es.string.split":203}],275:[function(t,x,v){function s(g){return(s=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(p){return typeof p}:function(p){return p&&typeof Symbol=="function"&&p.constructor===Symbol&&p!==Symbol.prototype?"symbol":typeof p})(g)}t("core-js/modules/es.symbol"),t("core-js/modules/es.symbol.description"),t("core-js/modules/es.symbol.iterator"),t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.for-each"),t("core-js/modules/es.array.includes"),t("core-js/modules/es.array.index-of"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.join"),t("core-js/modules/es.array.last-index-of"),t("core-js/modules/es.array.map"),t("core-js/modules/es.array.slice"),t("core-js/modules/es.function.name"),t("core-js/modules/es.map"),t("core-js/modules/es.number.constructor"),t("core-js/modules/es.object.get-own-property-descriptor"),t("core-js/modules/es.object.get-prototype-of"),t("core-js/modules/es.object.keys"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.reflect.construct"),t("core-js/modules/es.regexp.exec"),t("core-js/modules/es.regexp.to-string"),t("core-js/modules/es.set"),t("core-js/modules/es.string.includes"),t("core-js/modules/es.string.iterator"),t("core-js/modules/es.string.split"),t("core-js/modules/es.weak-map"),t("core-js/modules/web.dom-collections.for-each"),t("core-js/modules/web.dom-collections.iterator"),t("core-js/modules/es.symbol"),t("core-js/modules/es.symbol.description"),t("core-js/modules/es.symbol.iterator"),t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.for-each"),t("core-js/modules/es.array.includes"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.join"),t("core-js/modules/es.array.last-index-of"),t("core-js/modules/es.array.map"),t("core-js/modules/es.array.slice"),t("core-js/modules/es.function.name"),t("core-js/modules/es.number.constructor"),t("core-js/modules/es.object.keys"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.regexp.exec"),t("core-js/modules/es.regexp.to-string"),t("core-js/modules/es.set"),t("core-js/modules/es.string.includes"),t("core-js/modules/es.string.iterator"),t("core-js/modules/es.string.split"),t("core-js/modules/web.dom-collections.for-each"),t("core-js/modules/web.dom-collections.iterator"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0;var u=(u=t("../main"))&&u.__esModule?u:{default:u};(function(g){if(!(g&&g.__esModule)&&!(g===null||c(g)!=="object"&&typeof g!="function")){var p=o();if(p&&p.has(g))return p.get(g);var n,i={},a=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(n in g){var h;Object.prototype.hasOwnProperty.call(g,n)&&((h=a?Object.getOwnPropertyDescriptor(g,n):null)&&(h.get||h.set)?Object.defineProperty(i,n,h):i[n]=g[n])}i.default=g,p&&p.set(g,i)}})(t("../constants")),t("../internationalization");function o(){var g;return typeof WeakMap!="function"?null:(g=new WeakMap,o=function(){return g},g)}function c(g){return(c=typeof Symbol=="function"&&s(Symbol.iterator)==="symbol"?function(p){return s(p)}:function(p){return p&&typeof Symbol=="function"&&p.constructor===Symbol&&p!==Symbol.prototype?"symbol":s(p)})(g)}u.default._validateParameters=u.default._clearValidateParamsCache=function(){},t=u.default,v.default=t},{"../../../docs/parameterData.json":void 0,"../constants":269,"../internationalization":278,"../main":280,"core-js/modules/es.array.concat":152,"core-js/modules/es.array.for-each":160,"core-js/modules/es.array.includes":162,"core-js/modules/es.array.index-of":163,"core-js/modules/es.array.iterator":164,"core-js/modules/es.array.join":165,"core-js/modules/es.array.last-index-of":166,"core-js/modules/es.array.map":167,"core-js/modules/es.array.slice":168,"core-js/modules/es.function.name":173,"core-js/modules/es.map":174,"core-js/modules/es.number.constructor":178,"core-js/modules/es.object.get-own-property-descriptor":183,"core-js/modules/es.object.get-prototype-of":185,"core-js/modules/es.object.keys":186,"core-js/modules/es.object.to-string":187,"core-js/modules/es.reflect.construct":189,"core-js/modules/es.regexp.exec":192,"core-js/modules/es.regexp.to-string":193,"core-js/modules/es.set":194,"core-js/modules/es.string.includes":196,"core-js/modules/es.string.iterator":197,"core-js/modules/es.string.split":203,"core-js/modules/es.symbol":209,"core-js/modules/es.symbol.description":207,"core-js/modules/es.symbol.iterator":208,"core-js/modules/es.weak-map":241,"core-js/modules/web.dom-collections.for-each":242,"core-js/modules/web.dom-collections.iterator":243}],276:[function(t,x,v){function s(g){return(s=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(p){return typeof p}:function(p){return p&&typeof Symbol=="function"&&p.constructor===Symbol&&p!==Symbol.prototype?"symbol":typeof p})(g)}function u(g){return(u=typeof Symbol=="function"&&s(Symbol.iterator)==="symbol"?function(p){return s(p)}:function(p){return p&&typeof Symbol=="function"&&p.constructor===Symbol&&p!==Symbol.prototype?"symbol":s(p)})(g)}t("core-js/modules/es.symbol"),t("core-js/modules/es.symbol.description"),t("core-js/modules/es.symbol.iterator"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.object.get-own-property-descriptor"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.string.iterator"),t("core-js/modules/es.weak-map"),t("core-js/modules/web.dom-collections.iterator"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0;var o=function(g){if(g&&g.__esModule)return g;if(g===null||u(g)!=="object"&&typeof g!="function")return{default:g};var p=c();if(p&&p.has(g))return p.get(g);var n,i={},a=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(n in g){var h;Object.prototype.hasOwnProperty.call(g,n)&&((h=a?Object.getOwnPropertyDescriptor(g,n):null)&&(h.get||h.set)?Object.defineProperty(i,n,h):i[n]=g[n])}return i.default=g,p&&p.set(g,i),i}(t("./constants"));function c(){var g;return typeof WeakMap!="function"?null:(g=new WeakMap,c=function(){return g},g)}v.default={modeAdjust:function(g,p,n,i,a){return a===o.CORNER?{x:g,y:p,w:n,h:i}:a===o.CORNERS?{x:g,y:p,w:n-g,h:i-p}:a===o.RADIUS?{x:g-n,y:p-i,w:2*n,h:2*i}:a===o.CENTER?{x:g-.5*n,y:p-.5*i,w:n,h:i}:void 0}}},{"./constants":269,"core-js/modules/es.array.iterator":164,"core-js/modules/es.object.get-own-property-descriptor":183,"core-js/modules/es.object.to-string":187,"core-js/modules/es.string.iterator":197,"core-js/modules/es.symbol":209,"core-js/modules/es.symbol.description":207,"core-js/modules/es.symbol.iterator":208,"core-js/modules/es.weak-map":241,"core-js/modules/web.dom-collections.iterator":243}],277:[function(t,x,v){t("core-js/modules/es.array.iterator"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.promise"),t("core-js/modules/es.string.iterator"),t("core-js/modules/web.dom-collections.iterator"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.promise"),t("core-js/modules/es.string.iterator"),t("core-js/modules/web.dom-collections.iterator");var s=(u=t("../core/main"))&&u.__esModule?u:{default:u};t("./internationalization");var u=Promise.resolve();Promise.all([new Promise(function(o,c){document.readyState==="complete"?o():window.addEventListener("load",o,!1)}),u]).then(function(){window._setupDone!==void 0?console.warn("p5.js seems to have been imported multiple times. Please remove the duplicate import"):window.mocha||(window.setup&&typeof window.setup=="function"||window.draw&&typeof window.draw=="function")&&!s.default.instance&&new s.default})},{"../core/main":280,"./internationalization":278,"core-js/modules/es.array.iterator":164,"core-js/modules/es.object.to-string":187,"core-js/modules/es.promise":188,"core-js/modules/es.string.iterator":197,"core-js/modules/web.dom-collections.iterator":243}],278:[function(t,x,v){t("core-js/modules/es.array.includes"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.join"),t("core-js/modules/es.array.slice"),t("core-js/modules/es.object.keys"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.promise"),t("core-js/modules/es.regexp.exec"),t("core-js/modules/es.string.includes"),t("core-js/modules/es.string.iterator"),t("core-js/modules/es.string.split"),t("core-js/modules/web.dom-collections.iterator"),t("core-js/modules/es.array.includes"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.join"),t("core-js/modules/es.array.slice"),t("core-js/modules/es.object.keys"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.promise"),t("core-js/modules/es.regexp.exec"),t("core-js/modules/es.string.includes"),t("core-js/modules/es.string.iterator"),t("core-js/modules/es.string.split"),t("core-js/modules/web.dom-collections.iterator"),Object.defineProperty(v,"__esModule",{value:!0}),v.setTranslatorLanguage=v.currentTranslatorLanguage=v.availableTranslatorLanguages=v.initialize=v.translator=void 0;var s,u,o=g(t("i18next")),c=g(t("i18next-browser-languagedetector"));function g(i){return i&&i.__esModule?i:{default:i}}function p(i,a){for(var h=0;h=I.width||E>=I.height?[0,0,0,0]:this._getPixel(M,E);return L=new u.default.Image(k*C,P*C),L.pixelDensity(C),L.canvas.getContext("2d").drawImage(I,M,E,k*C,P*C,0,0,k*C,P*C),L}},{key:"textLeading",value:function(M){return typeof M=="number"?(this._setProperty("_leadingSet",!0),this._setProperty("_textLeading",M),this._pInst):this._textLeading}},{key:"textStyle",value:function(M){return M?(M!==o.NORMAL&&M!==o.ITALIC&&M!==o.BOLD&&M!==o.BOLDITALIC||this._setProperty("_textStyle",M),this._applyTextProperties()):this._textStyle}},{key:"textAscent",value:function(){return this._textAscent===null&&this._updateTextMetrics(),this._textAscent}},{key:"textDescent",value:function(){return this._textDescent===null&&this._updateTextMetrics(),this._textDescent}},{key:"textAlign",value:function(M,E){return M!==void 0?(this._setProperty("_textAlign",M),E!==void 0&&this._setProperty("_textBaseline",E),this._applyTextProperties()):{horizontal:this._textAlign,vertical:this._textBaseline}}},{key:"textWrap",value:function(M){return this._setProperty("_textWrap",M),this._textWrap}},{key:"text",value:function(M,E,k,P,L){var C,I,A,N,F=this._pInst,B=this._textWrap,q=Number.MAX_VALUE,V=k;if((this._doFill||this._doStroke)&&M!==void 0){if(C=(M=(M=typeof M!="string"?M.toString():M).replace(/(\t)/g," ")).split(` +`),P!==void 0){switch(this._rectMode===o.CENTER&&(E-=P/2),this._textAlign){case o.CENTER:E+=P/2;break;case o.RIGHT:E+=P}if(L!==void 0){this._rectMode===o.CENTER&&(k-=L/2,V-=L/2);var M=k,H=F.textAscent();switch(this._textBaseline){case o.BOTTOM:N=k+L,k=Math.max(N,k),V+=H;break;case o.CENTER:N=k+L/2,k=Math.max(N,k),V+=H/2}q=k+L-H,this._textBaseline===o.CENTER&&(q=M+L-H/2)}else this._textBaseline!==o.BOTTOM&&this._textBaseline!==o.CENTER||(V=k-(M=F.textSize()*this._textLeading)/2,q=k+M/2);if(B===o.WORD){for(var K=[],ee=0;eec.HALF_PI&&a<=3*c.HALF_PI?Math.atan(y/l*Math.tan(a))+c.PI:Math.atan(y/l*Math.tan(a))+c.TWO_PI,h=h<=c.HALF_PI?Math.atan(y/l*Math.tan(h)):h>c.HALF_PI&&h<=3*c.HALF_PI?Math.atan(y/l*Math.tan(h))+c.PI:Math.atan(y/l*Math.tan(h))+c.TWO_PI),hi||Math.abs(this.accelerationY-this.pAccelerationY)>i||Math.abs(this.accelerationZ-this.pAccelerationZ)>i)&&j.deviceMoved(),typeof j.deviceTurned=="function"&&(l=this._toDegrees(this.rotationX)+180,f=this._toDegrees(this.pRotationX)+180,y=u+180,0>>16,p[1+i]=(65280&n[a])>>>8,p[2+i]=255&n[a],p[3+i]=(4278190080&n[a])>>>24},_toImageData:function(p){return p instanceof ImageData?p:p.getContext("2d").getImageData(0,0,p.width,p.height)},_createImageData:function(p,n){return g._tmpCanvas=document.createElement("canvas"),g._tmpCtx=g._tmpCanvas.getContext("2d"),this._tmpCtx.createImageData(p,n)},apply:function(p,y,i){var a=p.getContext("2d"),h=a.getImageData(0,0,p.width,p.height),y=y(h,i);y instanceof ImageData?a.putImageData(y,0,0,0,0,p.width,p.height):a.putImageData(h,0,0,0,0,p.width,p.height)},threshold:function(p){for(var n=1>8)/a,i[h+1]=255*(l*n>>8)/a,i[h+2]=255*(f*n>>8)/a}},dilate:function(p){for(var n,i,a,h,y,l,f,m,b,j=g._toPixels(p),M=0,E=j.length?j.length/4:0,k=new Int32Array(E);M>16&255)+151*(h>>8&255)+28*(255&h))<(f=77*(b>>16&255)+151*(b>>8&255)+28*(255&b))&&(a=b,h=f),h<(f=77*((b=g._getARGB(j,m))>>16&255)+151*(b>>8&255)+28*(255&b))&&(a=b,h=f),h<(m=77*(y>>16&255)+151*(y>>8&255)+28*(255&y))&&(a=y,h=m),h<(b=77*(l>>16&255)+151*(l>>8&255)+28*(255&l))&&(a=l,h=b),k[M++]=a;g._setPixels(j,k)},erode:function(p){for(var n,i,a,h,y,l,f,m,b,j=g._toPixels(p),M=0,E=j.length?j.length/4:0,k=new Int32Array(E);M>16&255)+151*(b>>8&255)+28*(255&b))<(h=77*(h>>16&255)+151*(h>>8&255)+28*(255&h))&&(a=b,h=f),(f=77*((b=g._getARGB(j,m))>>16&255)+151*(b>>8&255)+28*(255&b))>16&255)+151*(y>>8&255)+28*(255&y))>16&255)+151*(l>>8&255)+28*(255&l))>>24],a+=B[(16711680&pe)>>16],h+=B[(65280&pe)>>8],y+=B[255&pe],i+=o[F],f++}ee[m=G+A]=l/i,ue[m]=a/i,T[m]=h/i,D[m]=y/i}G+=k}for(j=(b=-s)*k,N=G=0;N"+V.length.toString()+" out of "+N.toString()),z.next=48,new Promise(function(te){return setTimeout(te,0)});z.next=50;break;case 48:z.next=39;break;case 50:L||H.html("Frames processed, generating color palette..."),this.loop(),this.pixelDensity(q),ue=(0,n.GIFEncoder)(),T=function(te){for(var le=new Uint8Array(te.length*te[0].length),me=0;me"+J.toString()+" out of "+N.toString()),z.next=68,new Promise(function(te){return setTimeout(te,0)});case 68:J++,z.next=60;break;case 71:ue.finish(),pe=ue.bytesView(),pe=new Blob([pe],{type:"image/gif"}),V=[],this._recording=!1,this.loop(),L||(H.html("Done. Downloading your gif!🌸"),0=a&&(a=Math.floor(h.timeDisplayed/a),h.timeDisplayed=0,h.lastChangeTime=y,h.displayIndex+=a,h.loopCount=Math.floor(h.displayIndex/h.numFrames),h.loopLimit!==null&&h.loopCount>=h.loopLimit?h.playing=!1:(y=h.displayIndex%h.numFrames,this.drawingContext.putImageData(h.frames[y].image,0,0),h.displayIndex=y,this.setModified(!0))))}},{key:"_setProperty",value:function(i,a){this[i]=a,this.setModified(!0)}},{key:"loadPixels",value:function(){s.default.Renderer2D.prototype.loadPixels.call(this),this.setModified(!0)}},{key:"updatePixels",value:function(i,a,h,y){s.default.Renderer2D.prototype.updatePixels.call(this,i,a,h,y),this.setModified(!0)}},{key:"get",value:function(i,a,h,y){return s.default._validateParameters("p5.Image.get",arguments),s.default.Renderer2D.prototype.get.apply(this,arguments)}},{key:"_getPixel",value:function(){for(var i=arguments.length,a=new Array(i),h=0;h/g,">").replace(/"/g,""").replace(/'/g,"'")}function i(a,h){h&&h!==!0&&h!=="true"||(h="");var y="";return(a=a||"untitled")&&a.includes(".")&&(y=a.split(".").pop()),h&&y!==h&&(y=h,a="".concat(a,".").concat(y)),[a,y]}t("../core/friendly_errors/validate_params"),t("../core/friendly_errors/file_errors"),t("../core/friendly_errors/fes_core"),u.default.prototype.loadJSON=function(){for(var a=arguments.length,h=new Array(a),y=0;y"),f.print(""),f.print(' '),f.print(""),f.print(""),f.print(" "),m[0]!=="0"){f.print(" ");for(var k=0;k".concat(P)),f.print(" ")}f.print(" ")}for(var L=0;L");for(var C=0;C".concat(I)),f.print(" ")}f.print(" ")}f.print("
            "),f.print(""),f.print("")}f.close(),f.clear()},u.default.prototype.writeFile=function(f,h,y){var l="application/octet-stream",f=(u.default.prototype._isSafari()&&(l="text/plain"),new Blob(f,{type:l}));u.default.prototype.downloadFile(f,h,y)},u.default.prototype.downloadFile=function(a,f,m){var l,f=i(f,m),m=f[0];a instanceof Blob?c.default.saveAs(a,m):((l=document.createElement("a")).href=a,l.download=m,l.onclick=function(b){document.body.removeChild(b.target),b.stopPropagation()},l.style.display="none",document.body.appendChild(l),u.default.prototype._isSafari()&&(a=(a=`Hello, Safari user! To download this file... +1. Go to File --> Save As. +2. Choose "Page Source" as the Format. +`)+'3. Name it with this extension: ."'.concat(f[1],'"'),alert(a)),l.click())},u.default.prototype._checkFileExtension=i,u.default.prototype._isSafari=function(){return window.HTMLElement.toString().includes("Constructor")},t=u.default,v.default=t},{"../core/friendly_errors/fes_core":271,"../core/friendly_errors/file_errors":272,"../core/friendly_errors/validate_params":275,"../core/main":280,"core-js/modules/es.array.concat":152,"core-js/modules/es.array.includes":162,"core-js/modules/es.array.iterator":164,"core-js/modules/es.array.last-index-of":166,"core-js/modules/es.array.map":167,"core-js/modules/es.array.slice":168,"core-js/modules/es.array.splice":170,"core-js/modules/es.function.name":173,"core-js/modules/es.object.from-entries":182,"core-js/modules/es.object.to-string":187,"core-js/modules/es.promise":188,"core-js/modules/es.regexp.exec":192,"core-js/modules/es.regexp.to-string":193,"core-js/modules/es.string.includes":196,"core-js/modules/es.string.iterator":197,"core-js/modules/es.string.replace":201,"core-js/modules/es.string.split":203,"core-js/modules/es.symbol":209,"core-js/modules/es.symbol.description":207,"core-js/modules/es.symbol.iterator":208,"core-js/modules/es.typed-array.copy-within":210,"core-js/modules/es.typed-array.every":211,"core-js/modules/es.typed-array.fill":212,"core-js/modules/es.typed-array.filter":213,"core-js/modules/es.typed-array.find":215,"core-js/modules/es.typed-array.find-index":214,"core-js/modules/es.typed-array.for-each":218,"core-js/modules/es.typed-array.includes":219,"core-js/modules/es.typed-array.index-of":220,"core-js/modules/es.typed-array.iterator":223,"core-js/modules/es.typed-array.join":224,"core-js/modules/es.typed-array.last-index-of":225,"core-js/modules/es.typed-array.map":226,"core-js/modules/es.typed-array.reduce":228,"core-js/modules/es.typed-array.reduce-right":227,"core-js/modules/es.typed-array.reverse":229,"core-js/modules/es.typed-array.set":230,"core-js/modules/es.typed-array.slice":231,"core-js/modules/es.typed-array.some":232,"core-js/modules/es.typed-array.sort":233,"core-js/modules/es.typed-array.subarray":234,"core-js/modules/es.typed-array.to-locale-string":235,"core-js/modules/es.typed-array.to-string":236,"core-js/modules/es.typed-array.uint8-array":239,"core-js/modules/web.dom-collections.iterator":243,"core-js/modules/web.url":245,"es6-promise/auto":246,"fetch-jsonp":248,"file-saver":249,"whatwg-fetch":258}],307:[function(t,x,v){t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.index-of"),t("core-js/modules/es.array.join"),t("core-js/modules/es.array.splice"),t("core-js/modules/es.regexp.constructor"),t("core-js/modules/es.regexp.exec"),t("core-js/modules/es.regexp.to-string"),t("core-js/modules/es.string.match"),t("core-js/modules/es.string.replace"),t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.index-of"),t("core-js/modules/es.array.join"),t("core-js/modules/es.array.splice"),t("core-js/modules/es.regexp.constructor"),t("core-js/modules/es.regexp.exec"),t("core-js/modules/es.regexp.to-string"),t("core-js/modules/es.string.match"),t("core-js/modules/es.string.replace"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0;var s=(t=t("../core/main"))&&t.__esModule?t:{default:t};function u(o,c){for(var g=0;g>>0},getSeed:function(){return i},rand:function(){return(a=(1664525*a+1013904223)%h)/h}};y.setSeed(n),u=new Array(4096);for(var l=0;l<4096;l++)u[l]=y.rand()},p.default);v.default=p},{"../core/main":280}],313:[function(t,x,v){function s(i){return(s=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(a){return typeof a}:function(a){return a&&typeof Symbol=="function"&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a})(i)}function u(i){return(u=typeof Symbol=="function"&&s(Symbol.iterator)==="symbol"?function(a){return s(a)}:function(a){return a&&typeof Symbol=="function"&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":s(a)})(i)}t("core-js/modules/es.symbol"),t("core-js/modules/es.symbol.description"),t("core-js/modules/es.symbol.iterator"),t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.every"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.some"),t("core-js/modules/es.math.sign"),t("core-js/modules/es.number.constructor"),t("core-js/modules/es.number.is-finite"),t("core-js/modules/es.object.get-own-property-descriptor"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.string.iterator"),t("core-js/modules/es.string.sub"),t("core-js/modules/es.weak-map"),t("core-js/modules/web.dom-collections.iterator"),t("core-js/modules/es.array.concat"),t("core-js/modules/es.array.every"),t("core-js/modules/es.array.some"),t("core-js/modules/es.math.sign"),t("core-js/modules/es.number.constructor"),t("core-js/modules/es.number.is-finite"),t("core-js/modules/es.string.sub"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0;var o=(n=t("../core/main"))&&n.__esModule?n:{default:n},c=function(i){if(i&&i.__esModule)return i;if(i===null||u(i)!=="object"&&typeof i!="function")return{default:i};var a=g();if(a&&a.has(i))return a.get(i);var h,y={},l=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(h in i){var f;Object.prototype.hasOwnProperty.call(i,h)&&((f=l?Object.getOwnPropertyDescriptor(i,h):null)&&(f.get||f.set)?Object.defineProperty(y,h,f):y[h]=i[h])}return y.default=i,a&&a.set(i,y),y}(t("../core/constants"));function g(){var i;return typeof WeakMap!="function"?null:(i=new WeakMap,g=function(){return i},i)}function p(i,a){for(var h=0;h>>0},s.default.prototype.randomSeed=function(p){this._lcgSetSeed(u,p),this._gaussian_previous=!1},s.default.prototype.random=function(p,n){var i,a;return s.default._validateParameters("random",arguments),i=this[u]!=null?this._lcg(u):Math.random(),p===void 0?i:n===void 0?Array.isArray(p)?p[Math.floor(i*p.length)]:i*p:(nG&&(ce=H,J=F,ne=B,H=Z+G*($&&Z=o?c.substring(c.length-o,c.length):c}},s.default.prototype.unhex=function(u){return u instanceof Array?u.map(s.default.prototype.unhex):parseInt("0x".concat(u),16)},t=s.default,v.default=t},{"../core/main":280,"core-js/modules/es.array.map":167,"core-js/modules/es.number.constructor":178,"core-js/modules/es.object.to-string":187,"core-js/modules/es.regexp.to-string":193,"core-js/modules/es.string.repeat":200}],321:[function(t,x,v){t("core-js/modules/es.symbol"),t("core-js/modules/es.symbol.description"),t("core-js/modules/es.symbol.iterator"),t("core-js/modules/es.array.filter"),t("core-js/modules/es.array.index-of"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.join"),t("core-js/modules/es.array.map"),t("core-js/modules/es.array.slice"),t("core-js/modules/es.number.to-fixed"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.regexp.constructor"),t("core-js/modules/es.regexp.exec"),t("core-js/modules/es.regexp.to-string"),t("core-js/modules/es.string.iterator"),t("core-js/modules/es.string.match"),t("core-js/modules/es.string.pad-start"),t("core-js/modules/es.string.replace"),t("core-js/modules/es.string.split"),t("core-js/modules/es.string.trim"),t("core-js/modules/web.dom-collections.iterator"),t("core-js/modules/es.array.filter"),t("core-js/modules/es.array.index-of"),t("core-js/modules/es.array.join"),t("core-js/modules/es.array.map"),t("core-js/modules/es.array.slice"),t("core-js/modules/es.number.to-fixed"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.regexp.constructor"),t("core-js/modules/es.regexp.exec"),t("core-js/modules/es.regexp.to-string"),t("core-js/modules/es.string.match"),t("core-js/modules/es.string.pad-start"),t("core-js/modules/es.string.replace"),t("core-js/modules/es.string.split"),t("core-js/modules/es.string.trim"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0;var s=(n=t("../core/main"))&&n.__esModule?n:{default:n};function u(i,a){return function(h){if(Array.isArray(h))return h}(i)||function(h,y){if(Symbol.iterator in Object(h)||Object.prototype.toString.call(h)==="[object Arguments]"){var l=[],f=!0,m=!1,b=void 0;try{for(var j,M=h[Symbol.iterator]();!(f=(j=M.next()).done)&&(l.push(j.value),!y||l.length!==y);f=!0);}catch(E){m=!0,b=E}finally{try{f||M.return==null||M.return()}finally{if(m)throw b}}return l}}(i,a)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function o(i,a,h){var l=u(i.toString().split("."),2),y=l[0],l=l[1];return h===void 0?(y=y.padStart(a,"0"),l?y+"."+l:y):(y=(i=u(i.toFixed(h).toString().split("."),2))[0],l=i[1],y=y.padStart(a,"0"),l===void 0?y:y+"."+l)}function c(l,a){var h=(l=l.toString()).indexOf("."),y=h!==-1?l.substring(h):"",l=(l=h!==-1?l.substring(0,h):l).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",");if(a===0)y="";else if(a!==void 0)if(a>y.length)for(var f=a-(y+=h===-1?".":"").length+1,m=0;m=c.TWO_PI?"".concat(E="ellipse","|"):"".concat(E="arc","|").concat(f,"|").concat(m,"|").concat(b,"|")).concat(j,"|"),E=(this.geometryInHash(M)||((i=new o.default.Geometry(j,1,function(){if(f.toFixed(10)!==m.toFixed(10)){b!==c.PIE&&b!==void 0||(this.vertices.push(new o.default.Vector(.5,.5,0)),this.uvs.push([.5,.5]));for(var k=0;k<=j;k++){var L=(m-f)*(k/j)+f,P=.5+Math.cos(L)/2,L=.5+Math.sin(L)/2;this.vertices.push(new o.default.Vector(P,L,0)),this.uvs.push([P,L]),k>5&31)/31,(W>>10&31)/31)),new u.default.Vector(J,ne,ce)),pe=1;pe<=3;pe++){var Z=$+12*pe,Z=new u.default.Vector(ee.getFloat32(Z,!0),ee.getFloat32(4+Z,!0),ee.getFloat32(8+Z,!0));I.vertices.push(Z),I.vertexNormals.push(ie),T&&q.push(N,F,B)}I.faces.push([3*G,3*G+1,3*G+2]),I.uvs.push([0,0],[0,0],[0,0])}})(L,C);else{if(C=new DataView(C),!("TextDecoder"in window))return console.warn("Sorry, ASCII STL loading only works in browsers that support TextDecoder (https://caniuse.com/#feat=textencoder)");C=new TextDecoder("utf-8").decode(C).split(` +`),function(I,A){for(var N,F,B="",q=[],V=0;Vthis.cameraFar&&(a=this.cameraFar),Math.acos(Math.max(-1,Math.min(1,s.default.Vector.dot(h,y))))+b),b=p;(m<=0||m>=Math.PI)&&(this.upX*=-1,this.upY*=-1,this.upZ*=-1),y.mult(Math.cos(m)),f.mult(Math.cos(b)*Math.sin(m)),l.mult(Math.sin(b)*Math.sin(m)),h.set(y).add(f).add(l),this.eyeX=a*h.x+this.centerX,this.eyeY=a*h.y+this.centerY,this.eyeZ=a*h.z+this.centerZ,this.camera(this.eyeX,this.eyeY,this.eyeZ,this.centerX,this.centerY,this.centerZ,this.upX,this.upY,this.upZ)}},{key:"_orbitFree",value:function(m,b,M){var h=this.eyeX-this.centerX,y=this.eyeY-this.centerY,l=this.eyeZ-this.centerZ,a=Math.hypot(h,y,l),h=new s.default.Vector(h,y,l).normalize(),y=new s.default.Vector(this.upX,this.upY,this.upZ),l=s.default.Vector.cross(y,h).normalize(),f=s.default.Vector.cross(h,l),E=Math.atan2(b,m),E=(f.mult(Math.sin(E)),l.mult(Math.cos(E)).add(f),Math.sqrt(m*m+b*b)),f=s.default.Vector.cross(h,l),m=((a=(a*=Math.pow(10,M))this.cameraFar&&(a=this.cameraFar),Math.cos(E)),b=Math.sin(E),M=y.dot(h),E=y.dot(l),j=M*m+E*b,M=-M*b+E*m,E=y.dot(f);y.x=j*h.x+M*l.x+E*f.x,y.y=j*h.y+M*l.y+E*f.y,y.z=j*h.z+M*l.z+E*f.z,l.mult(-b),h.mult(m).add(l).mult(a),this.camera(h.x+this.centerX,h.y+this.centerY,h.z+this.centerZ,this.centerX,this.centerY,this.centerZ,y.x,y.y,y.z)}},{key:"_isActive",value:function(){return this===this._renderer._curCamera}}])&&u(c.prototype,g),o}(),s.default.prototype.setCamera=function(o){this._renderer._curCamera=o,this._renderer.uPMatrix.set(o.projMatrix)},t=s.default.Camera,v.default=t},{"../core/main":280,"core-js/modules/es.array.slice":168,"core-js/modules/es.math.hypot":175,"core-js/modules/es.string.sub":205}],330:[function(t,x,v){t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.slice"),t("core-js/modules/es.math.log2"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.typed-array.float32-array"),t("core-js/modules/es.typed-array.copy-within"),t("core-js/modules/es.typed-array.every"),t("core-js/modules/es.typed-array.fill"),t("core-js/modules/es.typed-array.filter"),t("core-js/modules/es.typed-array.find"),t("core-js/modules/es.typed-array.find-index"),t("core-js/modules/es.typed-array.for-each"),t("core-js/modules/es.typed-array.includes"),t("core-js/modules/es.typed-array.index-of"),t("core-js/modules/es.typed-array.iterator"),t("core-js/modules/es.typed-array.join"),t("core-js/modules/es.typed-array.last-index-of"),t("core-js/modules/es.typed-array.map"),t("core-js/modules/es.typed-array.reduce"),t("core-js/modules/es.typed-array.reduce-right"),t("core-js/modules/es.typed-array.reverse"),t("core-js/modules/es.typed-array.set"),t("core-js/modules/es.typed-array.slice"),t("core-js/modules/es.typed-array.some"),t("core-js/modules/es.typed-array.sort"),t("core-js/modules/es.typed-array.subarray"),t("core-js/modules/es.typed-array.to-locale-string"),t("core-js/modules/es.typed-array.to-string"),t("core-js/modules/es.array.iterator"),t("core-js/modules/es.array.slice"),t("core-js/modules/es.math.log2"),t("core-js/modules/es.object.to-string"),t("core-js/modules/es.typed-array.float32-array"),t("core-js/modules/es.typed-array.copy-within"),t("core-js/modules/es.typed-array.every"),t("core-js/modules/es.typed-array.fill"),t("core-js/modules/es.typed-array.filter"),t("core-js/modules/es.typed-array.find"),t("core-js/modules/es.typed-array.find-index"),t("core-js/modules/es.typed-array.for-each"),t("core-js/modules/es.typed-array.includes"),t("core-js/modules/es.typed-array.index-of"),t("core-js/modules/es.typed-array.iterator"),t("core-js/modules/es.typed-array.join"),t("core-js/modules/es.typed-array.last-index-of"),t("core-js/modules/es.typed-array.map"),t("core-js/modules/es.typed-array.reduce"),t("core-js/modules/es.typed-array.reduce-right"),t("core-js/modules/es.typed-array.reverse"),t("core-js/modules/es.typed-array.set"),t("core-js/modules/es.typed-array.slice"),t("core-js/modules/es.typed-array.some"),t("core-js/modules/es.typed-array.sort"),t("core-js/modules/es.typed-array.subarray"),t("core-js/modules/es.typed-array.to-locale-string"),t("core-js/modules/es.typed-array.to-string"),Object.defineProperty(v,"__esModule",{value:!0}),v.default=void 0,t=(t=t("../core/main"))&&t.__esModule?t:{default:t};function s(u,o){for(var c=0;c=this.width||I>=this.height)&&(console.warn("The x and y values passed to p5.Framebuffer.get are outside of its range and will be clamped."),C=this.target.constrain(C,0,this.width-1),I=this.target.constrain(I,0,this.height-1)),(0,p.readPixelWebGL)(this.gl,this.framebuffer,C*this.density,I*this.density,F.format,F.type);C=this.target.constrain(C,0,this.width-1),I=this.target.constrain(I,0,this.height-1),A=this.target.constrain(A,1,this.width-C),N=this.target.constrain(N,1,this.height-I);for(var B=(0,p.readPixelsWebGL)(void 0,this.gl,this.framebuffer,C*this.density,I*this.density,A*this.density,N*this.density,F.format,F.type),q=new Uint8ClampedArray(A*N*this.density*this.density*4),V=(q.fill(255),F.type===this.gl.RGB?3:4),H=0;Hthis.vertices.length-1-this.detailX;b--)l.add(this.vertexNormals[b]);l=o.default.Vector.div(l,this.detailX);for(var j=this.vertices.length-1;j>this.vertices.length-1-this.detailX;j--)this.vertexNormals[j]=l;return this}},{key:"_makeTriangleEdges",value:function(){for(var l=this.edges.length=0;l 65535 triangles. Your web browser does not support the WebGL Extension OES_element_index_uint.");h.drawElements(h.TRIANGLES,a.vertexCount,a.indexBufferType,0)}else h.drawArrays(n||h.TRIANGLES,0,a.vertexCount)},o.default.RendererGL.prototype._drawPoints=function(n,i){var a=this.GL,h=this._getImmediatePointShader();this._setPointUniforms(h),this._bindBuffer(i,a.ARRAY_BUFFER,this._vToNArray(n),Float32Array,a.STATIC_DRAW),h.enableAttrib(h.attributes.aPosition,3),this._applyColorBlend(this.curStrokeColor),a.drawArrays(a.Points,0,n.length),h.unbindShader()};var p=o.default.RendererGL;v.default=p},{"../core/constants":269,"../core/main":280,"./p5.RenderBuffer":334,"./p5.RendererGL":337,"core-js/modules/es.array.fill":155,"core-js/modules/es.array.iterator":164,"core-js/modules/es.array.some":169,"core-js/modules/es.object.get-own-property-descriptor":183,"core-js/modules/es.object.keys":186,"core-js/modules/es.object.to-string":187,"core-js/modules/es.string.iterator":197,"core-js/modules/es.symbol":209,"core-js/modules/es.symbol.description":207,"core-js/modules/es.symbol.iterator":208,"core-js/modules/es.typed-array.copy-within":210,"core-js/modules/es.typed-array.every":211,"core-js/modules/es.typed-array.fill":212,"core-js/modules/es.typed-array.filter":213,"core-js/modules/es.typed-array.find":215,"core-js/modules/es.typed-array.find-index":214,"core-js/modules/es.typed-array.float32-array":216,"core-js/modules/es.typed-array.for-each":218,"core-js/modules/es.typed-array.includes":219,"core-js/modules/es.typed-array.index-of":220,"core-js/modules/es.typed-array.iterator":223,"core-js/modules/es.typed-array.join":224,"core-js/modules/es.typed-array.last-index-of":225,"core-js/modules/es.typed-array.map":226,"core-js/modules/es.typed-array.reduce":228,"core-js/modules/es.typed-array.reduce-right":227,"core-js/modules/es.typed-array.reverse":229,"core-js/modules/es.typed-array.set":230,"core-js/modules/es.typed-array.slice":231,"core-js/modules/es.typed-array.some":232,"core-js/modules/es.typed-array.sort":233,"core-js/modules/es.typed-array.subarray":234,"core-js/modules/es.typed-array.to-locale-string":235,"core-js/modules/es.typed-array.to-string":236,"core-js/modules/es.typed-array.uint16-array":237,"core-js/modules/es.typed-array.uint32-array":238,"core-js/modules/es.weak-map":241,"core-js/modules/web.dom-collections.iterator":243}],337:[function(A,x,v){function s(H){return(s=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(K){return typeof K}:function(K){return K&&typeof Symbol=="function"&&K.constructor===Symbol&&K!==Symbol.prototype?"symbol":typeof K})(H)}function u(H){return(u=typeof Symbol=="function"&&s(Symbol.iterator)==="symbol"?function(K){return s(K)}:function(K){return K&&typeof Symbol=="function"&&K.constructor===Symbol&&K!==Symbol.prototype?"symbol":s(K)})(H)}A("core-js/modules/es.symbol"),A("core-js/modules/es.symbol.description"),A("core-js/modules/es.symbol.iterator"),A("core-js/modules/es.array.concat"),A("core-js/modules/es.array.copy-within"),A("core-js/modules/es.array.every"),A("core-js/modules/es.array.fill"),A("core-js/modules/es.array.flat"),A("core-js/modules/es.array.flat-map"),A("core-js/modules/es.array.from"),A("core-js/modules/es.array.includes"),A("core-js/modules/es.array.iterator"),A("core-js/modules/es.array.map"),A("core-js/modules/es.array.slice"),A("core-js/modules/es.array.some"),A("core-js/modules/es.array.unscopables.flat"),A("core-js/modules/es.array.unscopables.flat-map"),A("core-js/modules/es.map"),A("core-js/modules/es.object.assign"),A("core-js/modules/es.object.get-own-property-descriptor"),A("core-js/modules/es.object.get-prototype-of"),A("core-js/modules/es.object.to-string"),A("core-js/modules/es.reflect.construct"),A("core-js/modules/es.reflect.get"),A("core-js/modules/es.regexp.to-string"),A("core-js/modules/es.set"),A("core-js/modules/es.string.includes"),A("core-js/modules/es.string.iterator"),A("core-js/modules/es.typed-array.float32-array"),A("core-js/modules/es.typed-array.float64-array"),A("core-js/modules/es.typed-array.int16-array"),A("core-js/modules/es.typed-array.uint8-array"),A("core-js/modules/es.typed-array.uint16-array"),A("core-js/modules/es.typed-array.uint32-array"),A("core-js/modules/es.typed-array.copy-within"),A("core-js/modules/es.typed-array.every"),A("core-js/modules/es.typed-array.fill"),A("core-js/modules/es.typed-array.filter"),A("core-js/modules/es.typed-array.find"),A("core-js/modules/es.typed-array.find-index"),A("core-js/modules/es.typed-array.for-each"),A("core-js/modules/es.typed-array.includes"),A("core-js/modules/es.typed-array.index-of"),A("core-js/modules/es.typed-array.iterator"),A("core-js/modules/es.typed-array.join"),A("core-js/modules/es.typed-array.last-index-of"),A("core-js/modules/es.typed-array.map"),A("core-js/modules/es.typed-array.reduce"),A("core-js/modules/es.typed-array.reduce-right"),A("core-js/modules/es.typed-array.reverse"),A("core-js/modules/es.typed-array.set"),A("core-js/modules/es.typed-array.slice"),A("core-js/modules/es.typed-array.some"),A("core-js/modules/es.typed-array.sort"),A("core-js/modules/es.typed-array.subarray"),A("core-js/modules/es.typed-array.to-locale-string"),A("core-js/modules/es.typed-array.to-string"),A("core-js/modules/es.weak-map"),A("core-js/modules/web.dom-collections.iterator"),A("core-js/modules/es.symbol"),A("core-js/modules/es.symbol.description"),A("core-js/modules/es.symbol.iterator"),A("core-js/modules/es.array.concat"),A("core-js/modules/es.array.copy-within"),A("core-js/modules/es.array.every"),A("core-js/modules/es.array.fill"),A("core-js/modules/es.array.flat"),A("core-js/modules/es.array.flat-map"),A("core-js/modules/es.array.from"),A("core-js/modules/es.array.includes"),A("core-js/modules/es.array.iterator"),A("core-js/modules/es.array.map"),A("core-js/modules/es.array.slice"),A("core-js/modules/es.array.some"),A("core-js/modules/es.array.unscopables.flat"),A("core-js/modules/es.array.unscopables.flat-map"),A("core-js/modules/es.map"),A("core-js/modules/es.object.assign"),A("core-js/modules/es.object.to-string"),A("core-js/modules/es.set"),A("core-js/modules/es.string.includes"),A("core-js/modules/es.string.iterator"),A("core-js/modules/es.typed-array.float32-array"),A("core-js/modules/es.typed-array.float64-array"),A("core-js/modules/es.typed-array.int16-array"),A("core-js/modules/es.typed-array.uint8-array"),A("core-js/modules/es.typed-array.uint16-array"),A("core-js/modules/es.typed-array.uint32-array"),A("core-js/modules/es.typed-array.copy-within"),A("core-js/modules/es.typed-array.every"),A("core-js/modules/es.typed-array.fill"),A("core-js/modules/es.typed-array.filter"),A("core-js/modules/es.typed-array.find"),A("core-js/modules/es.typed-array.find-index"),A("core-js/modules/es.typed-array.for-each"),A("core-js/modules/es.typed-array.includes"),A("core-js/modules/es.typed-array.index-of"),A("core-js/modules/es.typed-array.iterator"),A("core-js/modules/es.typed-array.join"),A("core-js/modules/es.typed-array.last-index-of"),A("core-js/modules/es.typed-array.map"),A("core-js/modules/es.typed-array.reduce"),A("core-js/modules/es.typed-array.reduce-right"),A("core-js/modules/es.typed-array.reverse"),A("core-js/modules/es.typed-array.set"),A("core-js/modules/es.typed-array.slice"),A("core-js/modules/es.typed-array.some"),A("core-js/modules/es.typed-array.sort"),A("core-js/modules/es.typed-array.subarray"),A("core-js/modules/es.typed-array.to-locale-string"),A("core-js/modules/es.typed-array.to-string"),A("core-js/modules/web.dom-collections.iterator"),Object.defineProperty(v,"__esModule",{value:!0}),v.readPixelsWebGL=q,v.readPixelWebGL=V,v.default=void 0;var o=a(A("../core/main")),c=function(H){if(H&&H.__esModule)return H;if(H===null||u(H)!=="object"&&typeof H!="function")return{default:H};var K=i();if(K&&K.has(H))return K.get(H);var ee,ue={},T=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(ee in H){var D;Object.prototype.hasOwnProperty.call(H,ee)&&((D=T?Object.getOwnPropertyDescriptor(H,ee):null)&&(D.get||D.set)?Object.defineProperty(ue,ee,D):ue[ee]=H[ee])}return ue.default=H,K&&K.set(H,ue),ue}(A("../core/constants")),g=a(A("./GeometryBuilder")),p=a(A("libtess")),n=(A("./p5.Shader"),A("./p5.Camera"),A("../core/p5.Renderer"),A("./p5.Matrix"),A("./p5.Framebuffer"),A("path"),A("./p5.Texture"));function i(){var H;return typeof WeakMap!="function"?null:(H=new WeakMap,i=function(){return H},H)}function a(H){return H&&H.__esModule?H:{default:H}}function h(H){return function(K){if(Array.isArray(K)){for(var ee=0,ue=new Array(K.length);ee vTexCoord.y; + bool y1 = p1.y > vTexCoord.y; + bool y2 = p2.y > vTexCoord.y; + + // could web be under the curve (after t1)? + if (y1 ? !y2 : y0) { + // add the coverage for t1 + coverage.x += saturate(C1.x + 0.5); + // calculate the anti-aliasing for t1 + weight.x = min(weight.x, abs(C1.x)); + } + + // are we outside the curve (after t2)? + if (y1 ? !y0 : y2) { + // subtract the coverage for t2 + coverage.x -= saturate(C2.x + 0.5); + // calculate the anti-aliasing for t2 + weight.x = min(weight.x, abs(C2.x)); + } +} + +// this is essentially the same as coverageX, but with the axes swapped +void coverageY(vec2 p0, vec2 p1, vec2 p2) { + + vec2 C1, C2; + calulateCrossings(p0, p1, p2, C1, C2); + + bool x0 = p0.x > vTexCoord.x; + bool x1 = p1.x > vTexCoord.x; + bool x2 = p2.x > vTexCoord.x; + + if (x1 ? !x2 : x0) { + coverage.y -= saturate(C1.y + 0.5); + weight.y = min(weight.y, abs(C1.y)); + } + + if (x1 ? !x0 : x2) { + coverage.y += saturate(C2.y + 0.5); + weight.y = min(weight.y, abs(C2.y)); + } +} + +void main() { + + // calculate the pixel scale based on screen-coordinates + pixelScale = hardness / fwidth(vTexCoord); + + // which grid cell is this pixel in? + ivec2 gridCoord = ifloor(vTexCoord * vec2(uGridSize)); + + // intersect curves in this row + { + // the index into the row info bitmap + int rowIndex = gridCoord.y + uGridOffset.y; + // fetch the info texel + vec4 rowInfo = getTexel(uSamplerRows, rowIndex, uGridImageSize); + // unpack the rowInfo + int rowStrokeIndex = getInt16(rowInfo.xy); + int rowStrokeCount = getInt16(rowInfo.zw); + + for (int iRowStroke = INT(0); iRowStroke < N; iRowStroke++) { + if (iRowStroke >= rowStrokeCount) + break; + + // each stroke is made up of 3 points: the start and control point + // and the start of the next curve. + // fetch the indices of this pair of strokes: + vec4 strokeIndices = getTexel(uSamplerRowStrokes, rowStrokeIndex++, uCellsImageSize); + + // unpack the stroke index + int strokePos = getInt16(strokeIndices.xy); + + // fetch the two strokes + vec4 stroke0 = getTexel(uSamplerStrokes, strokePos + INT(0), uStrokeImageSize); + vec4 stroke1 = getTexel(uSamplerStrokes, strokePos + INT(1), uStrokeImageSize); + + // calculate the coverage + coverageX(stroke0.xy, stroke0.zw, stroke1.xy); + } + } + + // intersect curves in this column + { + int colIndex = gridCoord.x + uGridOffset.x; + vec4 colInfo = getTexel(uSamplerCols, colIndex, uGridImageSize); + int colStrokeIndex = getInt16(colInfo.xy); + int colStrokeCount = getInt16(colInfo.zw); + + for (int iColStroke = INT(0); iColStroke < N; iColStroke++) { + if (iColStroke >= colStrokeCount) + break; + + vec4 strokeIndices = getTexel(uSamplerColStrokes, colStrokeIndex++, uCellsImageSize); + + int strokePos = getInt16(strokeIndices.xy); + vec4 stroke0 = getTexel(uSamplerStrokes, strokePos + INT(0), uStrokeImageSize); + vec4 stroke1 = getTexel(uSamplerStrokes, strokePos + INT(1), uStrokeImageSize); + coverageY(stroke0.xy, stroke0.zw, stroke1.xy); + } + } + + weight = saturate(1.0 - weight * 2.0); + float distance = max(weight.x + weight.y, minDistance); // manhattan approx. + float antialias = abs(dot(coverage, weight) / distance); + float cover = min(abs(coverage.x), abs(coverage.y)); + OUT_COLOR = vec4(uMaterialColor.rgb, 1.) * uMaterialColor.a; + OUT_COLOR *= saturate(max(antialias, cover)); +} +`,lineVert:I+`/* + Part of the Processing project - http://processing.org + Copyright (c) 2012-15 The Processing Foundation + Copyright (c) 2004-12 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation, version 2.1. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +*/ + +#define PROCESSING_LINE_SHADER + +precision mediump int; + +uniform mat4 uModelViewMatrix; +uniform mat4 uProjectionMatrix; +uniform float uStrokeWeight; + +uniform bool uUseLineColor; +uniform vec4 uMaterialColor; + +uniform vec4 uViewport; +uniform int uPerspective; +uniform int uStrokeJoin; + +IN vec4 aPosition; +IN vec3 aTangentIn; +IN vec3 aTangentOut; +IN float aSide; +IN vec4 aVertexColor; + +OUT vec4 vColor; +OUT vec2 vTangent; +OUT vec2 vCenter; +OUT vec2 vPosition; +OUT float vMaxDist; +OUT float vCap; +OUT float vJoin; + +vec2 lineIntersection(vec2 aPoint, vec2 aDir, vec2 bPoint, vec2 bDir) { + // Rotate and translate so a starts at the origin and goes out to the right + bPoint -= aPoint; + vec2 rotatedBFrom = vec2( + bPoint.x*aDir.x + bPoint.y*aDir.y, + bPoint.y*aDir.x - bPoint.x*aDir.y + ); + vec2 bTo = bPoint + bDir; + vec2 rotatedBTo = vec2( + bTo.x*aDir.x + bTo.y*aDir.y, + bTo.y*aDir.x - bTo.x*aDir.y + ); + float intersectionDistance = + rotatedBTo.x + (rotatedBFrom.x - rotatedBTo.x) * rotatedBTo.y / + (rotatedBTo.y - rotatedBFrom.y); + return aPoint + aDir * intersectionDistance; +} + +void main() { + // Caps have one of either the in or out tangent set to 0 + vCap = (aTangentIn == vec3(0.)) != (aTangentOut == (vec3(0.))) + ? 1. : 0.; + + // Joins have two unique, defined tangents + vJoin = ( + aTangentIn != vec3(0.) && + aTangentOut != vec3(0.) && + aTangentIn != aTangentOut + ) ? 1. : 0.; + + vec4 posp = uModelViewMatrix * aPosition; + vec4 posqIn = uModelViewMatrix * (aPosition + vec4(aTangentIn, 0)); + vec4 posqOut = uModelViewMatrix * (aPosition + vec4(aTangentOut, 0)); + + float facingCamera = pow( + // The word space tangent's z value is 0 if it's facing the camera + abs(normalize(posqIn-posp).z), + + // Using pow() here to ramp \`facingCamera\` up from 0 to 1 really quickly + // so most lines get scaled and don't get clipped + 0.25 + ); + + // using a scale <1 moves the lines towards the camera + // in order to prevent popping effects due to half of + // the line disappearing behind the geometry faces. + float scale = mix(1., 0.995, facingCamera); + + // Moving vertices slightly toward the camera + // to avoid depth-fighting with the fill triangles. + // Discussed here: + // http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=252848 + posp.xyz = posp.xyz * scale; + posqIn.xyz = posqIn.xyz * scale; + posqOut.xyz = posqOut.xyz * scale; + + vec4 p = uProjectionMatrix * posp; + vec4 qIn = uProjectionMatrix * posqIn; + vec4 qOut = uProjectionMatrix * posqOut; + vCenter = p.xy; + + // formula to convert from clip space (range -1..1) to screen space (range 0..[width or height]) + // screen_p = (p.xy/p.w + <1,1>) * 0.5 * uViewport.zw + + // prevent division by W by transforming the tangent formula (div by 0 causes + // the line to disappear, see https://github.com/processing/processing/issues/5183) + // t = screen_q - screen_p + // + // tangent is normalized and we don't care which aDirection it points to (+-) + // t = +- normalize( screen_q - screen_p ) + // t = +- normalize( (q.xy/q.w+<1,1>)*0.5*uViewport.zw - (p.xy/p.w+<1,1>)*0.5*uViewport.zw ) + // + // extract common factor, <1,1> - <1,1> cancels out + // t = +- normalize( (q.xy/q.w - p.xy/p.w) * 0.5 * uViewport.zw ) + // + // convert to common divisor + // t = +- normalize( ((q.xy*p.w - p.xy*q.w) / (p.w*q.w)) * 0.5 * uViewport.zw ) + // + // remove the common scalar divisor/factor, not needed due to normalize and +- + // (keep uViewport - can't remove because it has different components for x and y + // and corrects for aspect ratio, see https://github.com/processing/processing/issues/5181) + // t = +- normalize( (q.xy*p.w - p.xy*q.w) * uViewport.zw ) + + vec2 tangentIn = normalize((qIn.xy*p.w - p.xy*qIn.w) * uViewport.zw); + vec2 tangentOut = normalize((qOut.xy*p.w - p.xy*qOut.w) * uViewport.zw); + + vec2 curPerspScale; + if(uPerspective == 1) { + // Perspective --- + // convert from world to clip by multiplying with projection scaling factor + // to get the right thickness (see https://github.com/processing/processing/issues/5182) + + // The y value of the projection matrix may be flipped if rendering to a Framebuffer. + // Multiplying again by its sign here negates the flip to get just the scale. + curPerspScale = (uProjectionMatrix * vec4(1, sign(uProjectionMatrix[1][1]), 0, 0)).xy; + } else { + // No Perspective --- + // multiply by W (to cancel out division by W later in the pipeline) and + // convert from screen to clip (derived from clip to screen above) + curPerspScale = p.w / (0.5 * uViewport.zw); + } + + vec2 offset; + if (vJoin == 1.) { + vTangent = normalize(tangentIn + tangentOut); + vec2 normalIn = vec2(-tangentIn.y, tangentIn.x); + vec2 normalOut = vec2(-tangentOut.y, tangentOut.x); + float side = sign(aSide); + float sideEnum = abs(aSide); + + // We generate vertices for joins on either side of the centerline, but + // the "elbow" side is the only one needing a join. By not setting the + // offset for the other side, all its vertices will end up in the same + // spot and not render, effectively discarding it. + if (sign(dot(tangentOut, vec2(-tangentIn.y, tangentIn.x))) != side) { + // Side enums: + // 1: the side going into the join + // 2: the middle of the join + // 3: the side going out of the join + if (sideEnum == 2.) { + // Calculate the position + tangent on either side of the join, and + // find where the lines intersect to find the elbow of the join + vec2 c = (posp.xy/posp.w + vec2(1.,1.)) * 0.5 * uViewport.zw; + vec2 intersection = lineIntersection( + c + (side * normalIn * uStrokeWeight / 2.), + tangentIn, + c + (side * normalOut * uStrokeWeight / 2.), + tangentOut + ); + offset = (intersection - c); + + // When lines are thick and the angle of the join approaches 180, the + // elbow might be really far from the center. We'll apply a limit to + // the magnitude to avoid lines going across the whole screen when this + // happens. + float mag = length(offset); + float maxMag = 3. * uStrokeWeight; + if (mag > maxMag) { + offset *= maxMag / mag; + } + } else if (sideEnum == 1.) { + offset = side * normalIn * uStrokeWeight / 2.; + } else if (sideEnum == 3.) { + offset = side * normalOut * uStrokeWeight / 2.; + } + } + if (uStrokeJoin == STROKE_JOIN_BEVEL) { + vec2 avgNormal = vec2(-vTangent.y, vTangent.x); + vMaxDist = abs(dot(avgNormal, normalIn * uStrokeWeight / 2.)); + } else { + vMaxDist = uStrokeWeight / 2.; + } + } else { + vec2 tangent = aTangentIn == vec3(0.) ? tangentOut : tangentIn; + vTangent = tangent; + vec2 normal = vec2(-tangent.y, tangent.x); + + float normalOffset = sign(aSide); + // Caps will have side values of -2 or 2 on the edge of the cap that + // extends out from the line + float tangentOffset = abs(aSide) - 1.; + offset = (normal * normalOffset + tangent * tangentOffset) * + uStrokeWeight * 0.5; + vMaxDist = uStrokeWeight / 2.; + } + vPosition = vCenter + offset; + + gl_Position.xy = p.xy + offset.xy * curPerspScale; + gl_Position.zw = p.zw; + + vColor = (uUseLineColor ? aVertexColor : uMaterialColor); +} +`,lineFrag:I+`precision mediump int; + +uniform vec4 uMaterialColor; +uniform int uStrokeCap; +uniform int uStrokeJoin; +uniform float uStrokeWeight; + +IN vec4 vColor; +IN vec2 vTangent; +IN vec2 vCenter; +IN vec2 vPosition; +IN float vMaxDist; +IN float vCap; +IN float vJoin; + +float distSquared(vec2 a, vec2 b) { + vec2 aToB = b - a; + return dot(aToB, aToB); +} + +void main() { + if (vCap > 0.) { + if ( + uStrokeCap == STROKE_CAP_ROUND && + distSquared(vPosition, vCenter) > uStrokeWeight * uStrokeWeight * 0.25 + ) { + discard; + } else if ( + uStrokeCap == STROKE_CAP_SQUARE && + dot(vPosition - vCenter, vTangent) > 0. + ) { + discard; + } + // Use full area for PROJECT + } else if (vJoin > 0.) { + if ( + uStrokeJoin == STROKE_JOIN_ROUND && + distSquared(vPosition, vCenter) > uStrokeWeight * uStrokeWeight * 0.25 + ) { + discard; + } else if (uStrokeJoin == STROKE_JOIN_BEVEL) { + vec2 normal = vec2(-vTangent.y, vTangent.x); + if (abs(dot(vPosition - vCenter, normal)) > vMaxDist) { + discard; + } + } + // Use full area for MITER + } + OUT_COLOR = vec4(vColor.rgb, 1.) * vColor.a; +} +`,pointVert:`IN vec3 aPosition; +uniform float uPointSize; +OUT float vStrokeWeight; +uniform mat4 uModelViewMatrix; +uniform mat4 uProjectionMatrix; +void main() { + vec4 positionVec4 = vec4(aPosition, 1.0); + gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; + gl_PointSize = uPointSize; + vStrokeWeight = uPointSize; +} +`,pointFrag:`precision mediump int; +uniform vec4 uMaterialColor; +IN float vStrokeWeight; + +void main(){ + float mask = 0.0; + + // make a circular mask using the gl_PointCoord (goes from 0 - 1 on a point) + // might be able to get a nicer edge on big strokeweights with smoothstep but slightly less performant + + mask = step(0.98, length(gl_PointCoord * 2.0 - 1.0)); + + // if strokeWeight is 1 or less lets just draw a square + // this prevents weird artifacting from carving circles when our points are really small + // if strokeWeight is larger than 1, we just use it as is + + mask = mix(0.0, mask, clamp(floor(vStrokeWeight - 0.5),0.0,1.0)); + + // throw away the borders of the mask + // otherwise we get weird alpha blending issues + + if(mask > 0.98){ + discard; + } + + OUT_COLOR = vec4(uMaterialColor.rgb, 1.) * uMaterialColor.a; +} +`,imageLightVert:`precision highp float; +attribute vec3 aPosition; +attribute vec3 aNormal; +attribute vec2 aTexCoord; + +varying vec3 localPos; +varying vec3 vWorldNormal; +varying vec3 vWorldPosition; +varying vec2 vTexCoord; + +uniform mat4 uModelViewMatrix; +uniform mat4 uProjectionMatrix; +uniform mat3 uNormalMatrix; + +void main() { + // Multiply the position by the matrix. + vec4 viewModelPosition = uModelViewMatrix * vec4(aPosition, 1.0); + gl_Position = uProjectionMatrix * viewModelPosition; + + // orient the normals and pass to the fragment shader + vWorldNormal = uNormalMatrix * aNormal; + + // send the view position to the fragment shader + vWorldPosition = (uModelViewMatrix * vec4(aPosition, 1.0)).xyz; + + localPos = vWorldPosition; + vTexCoord = aTexCoord; +} + + +/* +in the vertex shader we'll compute the world position and world oriented normal of the vertices and pass those to the fragment shader as varyings. +*/ +`,imageLightDiffusedFrag:`precision highp float; +varying vec3 localPos; + +// the HDR cubemap converted (can be from an equirectangular environment map.) +uniform sampler2D environmentMap; +varying vec2 vTexCoord; + +const float PI = 3.14159265359; + +vec2 nTOE( vec3 v ){ + // x = r sin(phi) cos(theta) + // y = r cos(phi) + // z = r sin(phi) sin(theta) + float phi = acos( v.y ); + // if phi is 0, then there are no x, z components + float theta = 0.0; + // else + theta = acos(v.x / sin(phi)); + float sinTheta = v.z / sin(phi); + if (sinTheta < 0.0) { + // Turn it into -theta, but in the 0-2PI range + theta = 2.0 * PI - theta; + } + theta = theta / (2.0 * 3.14159); + phi = phi / 3.14159 ; + + vec2 angles = vec2( phi, theta ); + return angles; +} + +float random(vec2 p) { + vec3 p3 = fract(vec3(p.xyx) * .1031); + p3 += dot(p3, p3.yzx + 33.33); + return fract((p3.x + p3.y) * p3.z); +} + +void main() +{ + // the sample direction equals the hemisphere's orientation + float phi = vTexCoord.x * 2.0 * PI; + float theta = vTexCoord.y * PI; + float x = sin(theta) * cos(phi); + float y = sin(theta) * sin(phi); + float z = cos(theta); + vec3 normal = vec3( x, y, z); + + // Discretely sampling the hemisphere given the integral's + // spherical coordinates translates to the following fragment code: + vec3 irradiance = vec3(0.0); + vec3 up = vec3(0.0, 1.0, 0.0); + vec3 right = normalize(cross(up, normal)); + up = normalize(cross(normal, right)); + + // We specify a fixed sampleDelta delta value to traverse + // the hemisphere; decreasing or increasing the sample delta + // will increase or decrease the accuracy respectively. + const float sampleDelta = 0.100; + float nrSamples = 0.0; + float randomOffset = random(gl_FragCoord.xy) * sampleDelta; + for(float rawPhi = 0.0; rawPhi < 2.0 * PI; rawPhi += sampleDelta) + { + float phi = rawPhi + randomOffset; + for(float rawTheta = 0.0; rawTheta < ( 0.5 ) * PI; rawTheta += sampleDelta) + { + float theta = rawTheta + randomOffset; + // spherical to cartesian (in tangent space) // tangent space to world // add each sample result to irradiance + float x = sin(theta) * cos(phi); + float y = sin(theta) * sin(phi); + float z = cos(theta); + vec3 tangentSample = vec3( x, y, z); + + vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * normal; + irradiance += (texture2D(environmentMap, nTOE(sampleVec)).xyz) * cos(theta) * sin(theta); + nrSamples++; + } + } + // divide by the total number of samples taken, giving us the average sampled irradiance. + irradiance = PI * irradiance * (1.0 / float(nrSamples )) ; + + + gl_FragColor = vec4(irradiance, 1.0); +}`,imageLightSpecularFrag:`precision highp float;\r +varying vec3 localPos;\r +varying vec2 vTexCoord;\r +\r +// our texture\r +uniform sampler2D environmentMap;\r +uniform float roughness;\r +\r +const float PI = 3.14159265359;\r +\r +float VanDerCorput(int bits);\r +vec2 HammersleyNoBitOps(int i, int N);\r +vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness);\r +\r +\r +vec2 nTOE( vec3 v ){\r + // x = r sin(phi) cos(theta) \r + // y = r cos(phi) \r + // z = r sin(phi) sin(theta)\r + float phi = acos( v.y );\r + // if phi is 0, then there are no x, z components\r + float theta = 0.0;\r + // else \r + theta = acos(v.x / sin(phi));\r + float sinTheta = v.z / sin(phi);\r + if (sinTheta < 0.0) {\r + // Turn it into -theta, but in the 0-2PI range\r + theta = 2.0 * PI - theta;\r + }\r + theta = theta / (2.0 * 3.14159);\r + phi = phi / 3.14159 ;\r + \r + vec2 angles = vec2( phi, theta );\r + return angles;\r +}\r +\r +\r +void main(){\r + const int SAMPLE_COUNT = 400; // 4096\r + int lowRoughnessLimit = int(pow(2.0,(roughness+0.1)*20.0));\r + float totalWeight = 0.0;\r + vec3 prefilteredColor = vec3(0.0);\r + float phi = vTexCoord.x * 2.0 * PI;\r + float theta = vTexCoord.y * PI;\r + float x = sin(theta) * cos(phi);\r + float y = sin(theta) * sin(phi);\r + float z = cos(theta);\r + vec3 N = vec3(x,y,z);\r + vec3 V = N;\r + for (int i = 0; i < SAMPLE_COUNT; ++i)\r + {\r + // break at smaller sample numbers for low roughness levels\r + if(i == lowRoughnessLimit)\r + {\r + break;\r + }\r + vec2 Xi = HammersleyNoBitOps(i, SAMPLE_COUNT);\r + vec3 H = ImportanceSampleGGX(Xi, N, roughness);\r + vec3 L = normalize(2.0 * dot(V, H) * H - V);\r +\r + float NdotL = max(dot(N, L), 0.0);\r + if (NdotL > 0.0)\r + {\r + prefilteredColor += texture2D(environmentMap, nTOE(L)).xyz * NdotL;\r + totalWeight += NdotL;\r + }\r + }\r + prefilteredColor = prefilteredColor / totalWeight;\r +\r + gl_FragColor = vec4(prefilteredColor, 1.0);\r +}\r +\r +vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness){\r + float a = roughness * roughness;\r +\r + float phi = 2.0 * PI * Xi.x;\r + float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));\r + float sinTheta = sqrt(1.0 - cosTheta * cosTheta);\r + // from spherical coordinates to cartesian coordinates\r + vec3 H;\r + H.x = cos(phi) * sinTheta;\r + H.y = sin(phi) * sinTheta;\r + H.z = cosTheta;\r +\r + // from tangent-space vector to world-space sample vector\r + vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);\r + vec3 tangent = normalize(cross(up, N));\r + vec3 bitangent = cross(N, tangent);\r +\r + vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;\r + return normalize(sampleVec);\r +}\r +\r +\r +float VanDerCorput(int n, int base)\r +{\r +#ifdef WEBGL2\r +\r + uint bits = uint(n);\r + bits = (bits << 16u) | (bits >> 16u);\r + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);\r + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);\r + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);\r + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);\r + return float(bits) * 2.3283064365386963e-10; // / 0x100000000\r +\r +#else\r +\r + float invBase = 1.0 / float(base);\r + float denom = 1.0;\r + float result = 0.0;\r +\r +\r + for (int i = 0; i < 32; ++i)\r + {\r + if (n > 0)\r + {\r + denom = mod(float(n), 2.0);\r + result += denom * invBase;\r + invBase = invBase / 2.0;\r + n = int(float(n) / 2.0);\r + }\r + }\r +\r +\r + return result;\r +\r +#endif\r +}\r +\r +vec2 HammersleyNoBitOps(int i, int N)\r +{\r + return vec2(float(i) / float(N), VanDerCorput(i, 2));\r +}\r +`},F=N.sphereMappingFrag;for(P in N)N[P]=`#ifdef WEBGL2 + +#define IN in +#define OUT out + +#ifdef FRAGMENT_SHADER +out vec4 outColor; +#define OUT_COLOR outColor +#endif +#define TEXTURE texture + +#else + +#ifdef FRAGMENT_SHADER +#define IN varying +#else +#define IN attribute +#endif +#define OUT varying +#define TEXTURE texture2D + +#ifdef FRAGMENT_SHADER +#define OUT_COLOR gl_FragColor +#endif + +#endif +`+N[P];M(A={},c.GRAY,`precision highp float; + +varying vec2 vTexCoord; + +uniform sampler2D tex0; + +float luma(vec3 color) { + // weighted grayscale with luminance values + return dot(color, vec3(0.2126, 0.7152, 0.0722)); +} + +void main() { + vec4 tex = texture2D(tex0, vTexCoord); + float gray = luma(tex.rgb); + gl_FragColor = vec4(gray, gray, gray, tex.a); +} +`),M(A,c.ERODE,`// Reduces the bright areas in an image + +precision highp float; + +varying vec2 vTexCoord; + +uniform sampler2D tex0; +uniform vec2 texelSize; + +float luma(vec3 color) { + // weighted grayscale with luminance values + // weights 77, 151, 28 taken from src/image/filters.js + return dot(color, vec3(0.300781, 0.589844, 0.109375)); +} + +void main() { + vec4 color = texture2D(tex0, vTexCoord); + float lum = luma(color.rgb); + + // set current color as the darkest neighbor color + + vec4 neighbors[4]; + neighbors[0] = texture2D(tex0, vTexCoord + vec2( texelSize.x, 0.0)); + neighbors[1] = texture2D(tex0, vTexCoord + vec2(-texelSize.x, 0.0)); + neighbors[2] = texture2D(tex0, vTexCoord + vec2(0.0, texelSize.y)); + neighbors[3] = texture2D(tex0, vTexCoord + vec2(0.0, -texelSize.y)); + + for (int i = 0; i < 4; i++) { + vec4 neighborColor = neighbors[i]; + float neighborLum = luma(neighborColor.rgb); + + if (neighborLum < lum) { + color = neighborColor; + lum = neighborLum; + } + } + + gl_FragColor = color; +} +`),M(A,c.DILATE,`// Increase the bright areas in an image + +precision highp float; + +varying vec2 vTexCoord; + +uniform sampler2D tex0; +uniform vec2 texelSize; + +float luma(vec3 color) { + // weighted grayscale with luminance values + // weights 77, 151, 28 taken from src/image/filters.js + return dot(color, vec3(0.300781, 0.589844, 0.109375)); +} + +void main() { + vec4 color = texture2D(tex0, vTexCoord); + float lum = luma(color.rgb); + + // set current color as the brightest neighbor color + + vec4 neighbors[4]; + neighbors[0] = texture2D(tex0, vTexCoord + vec2( texelSize.x, 0.0)); + neighbors[1] = texture2D(tex0, vTexCoord + vec2(-texelSize.x, 0.0)); + neighbors[2] = texture2D(tex0, vTexCoord + vec2(0.0, texelSize.y)); + neighbors[3] = texture2D(tex0, vTexCoord + vec2(0.0, -texelSize.y)); + + for (int i = 0; i < 4; i++) { + vec4 neighborColor = neighbors[i]; + float neighborLum = luma(neighborColor.rgb); + + if (neighborLum > lum) { + color = neighborColor; + lum = neighborLum; + } + } + + gl_FragColor = color; +} +`),M(A,c.BLUR,`precision highp float; + +// Two-pass blur filter, unweighted kernel. +// See also a similar blur at Adam Ferriss' repo of shader examples: +// https://github.com/aferriss/p5jsShaderExamples/blob/gh-pages/4_image-effects/4-9_single-pass-blur/effect.frag + + +uniform sampler2D tex0; +varying vec2 vTexCoord; +uniform vec2 direction; +uniform vec2 canvasSize; +uniform float radius; + +float random(vec2 p) { + vec3 p3 = fract(vec3(p.xyx) * .1031); + p3 += dot(p3, p3.yzx + 33.33); + return fract((p3.x + p3.y) * p3.z); +} + +// This isn't a real Gaussian weight, it's a quadratic weight. It's what the +// CPU mode's blur uses though, so we also use it here to match. +float quadWeight(float x, float e) { + return pow(e-abs(x), 2.); +} + +void main(){ + vec2 uv = vTexCoord; + + // A reasonable maximum number of samples + const float maxSamples = 64.0; + + float numSamples = floor(7. * radius); + if (fract(numSamples / 2.) == 0.) { + numSamples++; + } + vec4 avg = vec4(0.0); + float total = 0.0; + + // Calculate the spacing to avoid skewing if numSamples > maxSamples + float spacing = 1.0; + if (numSamples > maxSamples) { + spacing = numSamples / maxSamples; + numSamples = maxSamples; + } + + float randomOffset = (spacing - 1.0) * mix(-0.5, 0.5, random(gl_FragCoord.xy)); + for (float i = 0.0; i < maxSamples; i++) { + if (i >= numSamples) break; + + float sample = i * spacing - (numSamples - 1.0) * 0.5 * spacing + randomOffset; + vec2 sampleCoord = uv + vec2(sample, sample) / canvasSize * direction; + float weight = quadWeight(sample, (numSamples - 1.0) * 0.5 * spacing); + + avg += weight * texture2D(tex0, sampleCoord); + total += weight; + } + + avg /= total; + gl_FragColor = avg; +} +`),M(A,c.POSTERIZE,`// Limit color space for a stylized cartoon / poster effect + +precision highp float; + +varying vec2 vTexCoord; + +uniform sampler2D tex0; +uniform float filterParameter; + +vec3 quantize(vec3 color, float n) { + // restrict values to N options/bins + // and floor each channel to nearest value + // + // eg. when N = 5, values = 0.0, 0.25, 0.50, 0.75, 1.0 + // then quantize (0.1, 0.7, 0.9) -> (0.0, 0.5, 1.0) + + color = color * n; + color = floor(color); + color = color / (n - 1.0); + return color; +} + +void main() { + vec4 color = texture2D(tex0, vTexCoord); + + vec3 restrictedColor = quantize(color.rgb / color.a, filterParameter); + + gl_FragColor = vec4(restrictedColor.rgb * color.a, color.a); +} +`),M(A,c.OPAQUE,`// Set alpha channel to entirely opaque + +precision highp float; + +varying vec2 vTexCoord; + +uniform sampler2D tex0; + +void main() { + vec4 color = texture2D(tex0, vTexCoord); + gl_FragColor = vec4(color.rgb / color.a, 1.0); +} +`),M(A,c.INVERT,`// Set each pixel to inverse value +// Note that original INVERT does not change the opacity, so this follows suit + +precision highp float; + +varying vec2 vTexCoord; + +uniform sampler2D tex0; + +void main() { +vec4 color = texture2D(tex0, vTexCoord); +vec3 origColor = color.rgb / color.a; +vec3 invertedColor = vec3(1.0) - origColor; +gl_FragColor = vec4(invertedColor * color.a, color.a); +} +`),M(A,c.THRESHOLD,`// Convert pixels to either white or black, +// depending on if their luma is above or below filterParameter + +precision highp float; + +varying vec2 vTexCoord; + +uniform sampler2D tex0; +uniform float filterParameter; + +float luma(vec3 color) { + // weighted grayscale with luminance values + return dot(color, vec3(0.2126, 0.7152, 0.0722)); +} + +void main() { + vec4 color = texture2D(tex0, vTexCoord); + float gray = luma(color.rgb / color.a); + // floor() used to match src/image/filters.js + float threshold = floor(filterParameter * 255.0) / 255.0; + float blackOrWhite = step(threshold, gray); + gl_FragColor = vec4(vec3(blackOrWhite) * color.a, color.a); +} +`);var B=A;function q(H,K,ce,ue,T,D,G,W,$,J){var ne=K.getParameter(K.FRAMEBUFFER_BINDING),ce=(K.bindFramebuffer(K.FRAMEBUFFER,ce),W===K.RGBA?4:3),ie=D*G*ce,pe=$===K.UNSIGNED_BYTE?Uint8Array:Float32Array;if(H instanceof pe&&H.length===ie||(H=new pe(ie)),K.readPixels(ue,J?J-T-G:T,D,G,W,$,H),K.bindFramebuffer(K.FRAMEBUFFER,ne),J)for(var Z=Math.floor(G/2),z=new pe(D*ce),te=0;te>7,127&xe,ae>>7,127&ae);for(var Se=0;Se>7,127&Pe,0,0)}}return{cellImageInfo:re,dimOffset:Le,dimImageInfo:we}}}}]),m}();c.default.RendererGL.prototype._renderText=function(m,b,j,M,E){if(this._textFont&&typeof this._textFont!="string"){if(!(E<=M)&&this._doFill){if(this._isOpenType()){m.push();var E=this._doStroke,k=this.drawMode,P=(this._doStroke=!1,this.drawMode=g.TEXTURE,this._textFont.font),L=(L=this._textFont._fontInfo)||(this._textFont._fontInfo=new f(P)),j=this._textFont._handleAlignment(this,b,j,M),M=this._textSize/P.unitsPerEm,C=(this.translate(j.x,j.y,0),this.scale(M,M,1),this.GL),j=!this._defaultFontShader,I=this._getFontShader(),A=(I.init(),I.bindShader(),j&&(I.setUniform("uGridImageSize",[64,64]),I.setUniform("uCellsImageSize",[64,64]),I.setUniform("uStrokeImageSize",[64,64]),I.setUniform("uGridSize",[9,9])),this._applyColorBlend(this.curFillColor),this.retainedMode.geometry.glyph),N=(A||((M=this._textGeom=new c.default.Geometry(1,1,function(){for(var pe=0;pe<=1;pe++)for(var Z=0;Z<=1;Z++)this.vertices.push(new c.default.Vector(Z,pe,0)),this.uvs.push(Z,pe)})).computeFaces().computeNormals(),A=this.createBuffers("glyph",M)),!0),j=!1,M=void 0;try{for(var F,B=this.retainedMode.buffers.text[Symbol.iterator]();!(N=(F=B.next()).done);N=!0)F.value._prepareBuffer(A,I)}catch(pe){j=!0,M=pe}finally{try{N||B.return==null||B.return()}finally{if(j)throw M}}this._bindBuffer(A.indexBuffer,C.ELEMENT_ARRAY_BUFFER),I.setUniform("uMaterialColor",this.curFillColor),C.pixelStorei(C.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1);try{var q=0,V=null,H=P.stringToGlyphs(b),K=!0,ee=!1,ue=void 0;try{for(var T,D=H[Symbol.iterator]();!(K=(T=D.next()).done);K=!0){var G,W,$=T.value,J=(V&&(q+=P.getKerningValue(V,$)),L.getGlyphInfo($));J.uGlyphRect&&(G=J.rowInfo,W=J.colInfo,I.setUniform("uSamplerStrokes",J.strokeImageInfo.imageData),I.setUniform("uSamplerRowStrokes",G.cellImageInfo.imageData),I.setUniform("uSamplerRows",G.dimImageInfo.imageData),I.setUniform("uSamplerColStrokes",W.cellImageInfo.imageData),I.setUniform("uSamplerCols",W.dimImageInfo.imageData),I.setUniform("uGridOffset",J.uGridOffset),I.setUniform("uGlyphRect",J.uGlyphRect),I.setUniform("uGlyphOffset",q),I.bindTextures(),C.drawElements(C.TRIANGLES,6,this.GL.UNSIGNED_SHORT,0)),q+=$.advanceWidth,V=$}}catch(pe){ee=!0,ue=pe}finally{try{K||D.return==null||D.return()}finally{if(ee)throw ue}}}finally{I.unbindShader(),this._doStroke=E,this.drawMode=k,C.pixelStorei(C.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!0),m.pop()}}else console.log("WEBGL: only Opentype (.otf) and Truetype (.ttf) fonts are supported");return m}}else console.log("WEBGL: you must load and set a font before drawing text. See `loadFont` and `textFont` for more details.")}},{"../core/constants":269,"../core/main":280,"./p5.RendererGL.Retained":336,"./p5.Shader":338,"core-js/modules/es.array.iterator":164,"core-js/modules/es.object.get-own-property-descriptor":183,"core-js/modules/es.object.to-string":187,"core-js/modules/es.regexp.exec":192,"core-js/modules/es.string.iterator":197,"core-js/modules/es.string.split":203,"core-js/modules/es.string.sub":205,"core-js/modules/es.symbol":209,"core-js/modules/es.symbol.description":207,"core-js/modules/es.symbol.iterator":208,"core-js/modules/es.weak-map":241,"core-js/modules/web.dom-collections.iterator":243}]},{},[264])(264)})})(Jf);var Vb=Jf.exports;const Pc=Gb(Vb),Hb=gn(()=>({provide:{p5:Pc,p5:Pc}})),zb=[I0,F0,Zv,Qv,Jv,Fb,Nb,Bb,Hb],Wb=hr({props:{vnode:{type:Object,required:!0},route:{type:Object,required:!0},vnodeRef:Object,renderKey:String,trackRootNodes:Boolean},setup(r){const d=r.renderKey,w=r.route,t={};for(const x in r.route)Object.defineProperty(t,x,{get:()=>d===r.renderKey?r.route[x]:w[x]});return Wr(ps,is(t)),()=>tr(r.vnode,{ref:r.vnodeRef})}}),qb=hr({name:"NuxtPage",inheritAttrs:!1,props:{name:{type:String},transition:{type:[Boolean,Object],default:void 0},keepalive:{type:[Boolean,Object],default:void 0},route:{type:Object},pageKey:{type:[Function,String],default:null}},setup(r,{attrs:d,expose:w}){const t=It(),x=mt(),v=Ht(ps,null);let s;w({pageRef:x});const u=Ht(xf,null);let o;const c=t.deferHydration();if(t.isHydrating){const g=t.hooks.hookOnce("app:error",c);qr().beforeEach(g)}return r.pageKey&&In(()=>r.pageKey,(g,p)=>{g!==p&&t.callHook("page:loading:start")}),()=>tr(Kf,{name:r.name,route:r.route,...d},{default:g=>{const p=Yb(v,g.route,g.Component),n=v&&v.matched.length===g.route.matched.length;if(!g.Component){if(o&&!n)return o;c();return}if(o&&u&&!u.isCurrent(g.route))return o;if(p&&v&&(!u||u!=null&&u.isCurrent(v)))return n?o:null;const i=Ia(g,r.pageKey);!t.isHydrating&&!$b(v,g.route,g.Component)&&s===i&&t.callHook("page:loading:end"),s=i;const a=!!(r.transition??g.route.meta.pageTransition??Pa),h=a&&Xb([r.transition,g.route.meta.pageTransition,Pa,{onAfterLeave:()=>{t.callHook("page:transition:finish",g.Component)}}].filter(Boolean)),y=r.keepalive??g.route.meta.keepalive??T0;return o=Qf(fs,a&&h,Vv(y,tr(rl,{suspensible:!0,onPending:()=>t.callHook("page:start",g.Component),onResolve:()=>{Ur(()=>t.callHook("page:finish",g.Component).then(()=>t.callHook("page:loading:end")).finally(c))}},{default:()=>{const l=tr(Wb,{key:i||void 0,vnode:g.Component,route:g.route,renderKey:i||void 0,trackRootNodes:a,vnodeRef:x});return y&&(l.type.name=g.Component.type.name||g.Component.type.__name||"RouteProvider"),l}}))).default(),o}})}});function Xb(r){const d=r.map(w=>({...w,onAfterLeave:w.onAfterLeave?vl(w.onAfterLeave):void 0}));return _f(...d)}function Yb(r,d,w){if(!r)return!1;const t=d.matched.findIndex(x=>{var v;return((v=x.components)==null?void 0:v.default)===(w==null?void 0:w.type)});return!t||t===-1?!1:d.matched.slice(0,t).some((x,v)=>{var s,u,o;return((s=x.components)==null?void 0:s.default)!==((o=(u=r.matched[v])==null?void 0:u.components)==null?void 0:o.default)})||w&&Ia({route:d,Component:w})!==Ia({route:r,Component:w})}function $b(r,d,w){return r?d.matched.findIndex(x=>{var v;return((v=x.components)==null?void 0:v.default)===(w==null?void 0:w.type)})t.default||t);return()=>tr(w,r.layoutProps,d.slots)}}),Kb=hr({name:"NuxtLayout",inheritAttrs:!1,props:{name:{type:[String,Boolean,Object],default:null},fallback:{type:[String,Object],default:null}},setup(r,d){const w=It(),t=Ht(ps),x=t===hi()?Bv():t,v=jt(()=>{let o=Bt(r.name)??x.meta.layout??"default";return o&&!(o in Pn)&&r.fallback&&(o=Bt(r.fallback)),o}),s=mt();d.expose({layoutRef:s});const u=w.deferHydration();if(w.isHydrating){const o=w.hooks.hookOnce("app:error",u);qr().beforeEach(o)}return()=>{const o=v.value&&v.value in Pn,c=x.meta.layoutTransition??E0;return Qf(fs,o&&c,{default:()=>tr(rl,{suspensible:!0,onResolve:()=>{Ur(u)}},{default:()=>tr(Qb,{layoutProps:Kd(d.attrs,{ref:s}),key:v.value||void 0,name:v.value,shouldProvide:!r.name,hasTransition:!!c},d.slots)})}).default()}}}),Qb=hr({name:"NuxtLayoutProvider",inheritAttrs:!1,props:{name:{type:[String,Boolean]},layoutProps:{type:Object},hasTransition:{type:Boolean},shouldProvide:{type:Boolean}},setup(r,d){const w=r.name;return r.shouldProvide&&Wr(xf,{isCurrent:t=>w===(t.meta.layout??"default")}),()=>{var t,x;return!w||typeof w=="string"&&!(w in Pn)?(x=(t=d.slots).default)==null?void 0:x.call(t):tr(Zb,{key:w,layoutProps:r.layoutProps,name:w},d.slots)}}}),Jb={class:"bg-background"},e1=hr({__name:"app",setup(r){return x0({title:"Colton Padden",ogTitle:"Colton Padden",description:"This is where you can find the blog, portfolio, and experiments of Colton Padden.",ogDescription:"This is where you can find the blog, portfolio, and experiments of Colton Padden."}),(d,w)=>{const t=qb,x=Kb;return Fr(),cs("body",Jb,[ft(x,null,{default:Ir(()=>[ft(t)]),_:1})])}}}),eh=(r,d)=>{const w=r.__vccOpts||r;for(const[t,x]of d)w[t]=x;return w},t1={},r1={class:"hover:text-orange-500",width:"366",height:"24",viewBox:"0 0 366 24",fill:"none",xmlns:"http://www.w3.org/2000/svg"},n1=xm('',6),o1=[n1];function s1(r,d){return Fr(),cs("svg",r1,o1)}const i1=eh(t1,[["render",s1]]);async function th(r,d=qr()){const{path:w,matched:t}=d.resolve(r);if(!t.length||(d._routePreloaded||(d._routePreloaded=new Set),d._routePreloaded.has(w)))return;const x=d._preloadPromises=d._preloadPromises||[];if(x.length>4)return Promise.all(x).then(()=>th(r,d));d._routePreloaded.add(w);const v=t.map(s=>{var u;return(u=s.components)==null?void 0:u.default}).filter(s=>typeof s=="function");for(const s of v){const u=Promise.resolve(s()).catch(()=>{}).finally(()=>x.splice(x.indexOf(u)));x.push(u)}await Promise.all(x)}const a1=(...r)=>r.find(d=>d!==void 0);function l1(r){const d=r.componentName||"NuxtLink";function w(t,x){if(!t||r.trailingSlash!=="append"&&r.trailingSlash!=="remove")return t;if(typeof t=="string")return Ac(t,r.trailingSlash);const v="path"in t&&t.path!==void 0?t.path:x(t).path;return{...t,name:void 0,path:Ac(v,r.trailingSlash)}}return hr({name:d,props:{to:{type:[String,Object],default:void 0,required:!1},href:{type:[String,Object],default:void 0,required:!1},target:{type:String,default:void 0,required:!1},rel:{type:String,default:void 0,required:!1},noRel:{type:Boolean,default:void 0,required:!1},prefetch:{type:Boolean,default:void 0,required:!1},noPrefetch:{type:Boolean,default:void 0,required:!1},activeClass:{type:String,default:void 0,required:!1},exactActiveClass:{type:String,default:void 0,required:!1},prefetchedClass:{type:String,default:void 0,required:!1},replace:{type:Boolean,default:void 0,required:!1},ariaCurrentValue:{type:String,default:void 0,required:!1},external:{type:Boolean,default:void 0,required:!1},custom:{type:Boolean,default:void 0,required:!1}},setup(t,{slots:x}){const v=qr(),s=fi(),u=jt(()=>{const a=t.to||t.href||"";return w(a,v.resolve)}),o=jt(()=>typeof u.value=="string"&&yn(u.value,{acceptRelative:!0})),c=jt(()=>t.target&&t.target!=="_self"),g=jt(()=>t.external||c.value?!0:typeof u.value=="object"?!1:u.value===""||o.value),p=mt(!1),n=mt(null),i=a=>{var h;n.value=t.custom?(h=a==null?void 0:a.$el)==null?void 0:h.nextElementSibling:a==null?void 0:a.$el};if(t.prefetch!==!1&&t.noPrefetch!==!0&&t.target!=="_blank"&&!d1()){const h=It();let y,l=null;Qr(()=>{const f=c1();bl(()=>{y=Da(()=>{var m;(m=n==null?void 0:n.value)!=null&&m.tagName&&(l=f.observe(n.value,async()=>{l==null||l(),l=null;const b=typeof u.value=="string"?u.value:v.resolve(u.value).fullPath;await Promise.all([h.hooks.callHook("link:prefetch",b).catch(()=>{}),!g.value&&th(u.value,v).catch(()=>{})]),p.value=!0}))})})}),ls(()=>{y&&Kv(y),l==null||l(),l=null})}return()=>{var l,f;if(!g.value){const m={ref:i,to:u.value,activeClass:t.activeClass||r.activeClass,exactActiveClass:t.exactActiveClass||r.exactActiveClass,replace:t.replace,ariaCurrentValue:t.ariaCurrentValue,custom:t.custom};return t.custom||(p.value&&(m.class=t.prefetchedClass||r.prefetchedClass),m.rel=t.rel||void 0),tr(Pp("RouterLink"),m,x.default)}const a=typeof u.value=="object"?((l=v.resolve(u.value))==null?void 0:l.href)??null:u.value&&!t.external&&!o.value?w(di(s.app.baseURL,u.value),v.resolve):u.value||null,h=t.target||null,y=a1(t.noRel?"":t.rel,r.externalRelAttribute,o.value||c.value?"noopener noreferrer":"")||null;if(t.custom){if(!x.default)return null;const m=()=>Sg(a,{replace:t.replace,external:t.external});return x.default({href:a,navigate:m,get route(){if(!a)return;const b=hs(a);return{path:b.pathname,fullPath:b.pathname,get query(){return af(b.search)},hash:b.hash,params:{},name:void 0,matched:[],redirectedFrom:void 0,meta:{},href:a}},rel:y,target:h,isExternal:g.value,isActive:!1,isExactActive:!1})}return tr("a",{ref:n,href:a,rel:y,target:h},(f=x.default)==null?void 0:f.call(x))}}})}const u1=l1(M0);function Ac(r,d){const w=d==="append"?Ks:ci;return yn(r)&&!r.startsWith("http")?r:w(r,!0)}function c1(){const r=It();if(r._observer)return r._observer;let d=null;const w=new Map,t=(v,s)=>(d||(d=new IntersectionObserver(u=>{for(const o of u){const c=w.get(o.target);(o.isIntersecting||o.intersectionRatio>0)&&c&&c()}})),w.set(v,s),d.observe(v),()=>{w.delete(v),d.unobserve(v),w.size===0&&(d.disconnect(),d=null)});return r._observer={observe:t}}function d1(){const r=navigator.connection;return!!(r&&(r.saveData||/2g/.test(r.effectiveType)))}let f1=Symbol("headlessui.useid"),h1=0;function vi(){return Ht(f1,()=>`${++h1}`)()}function Ft(r){var d;if(r==null||r.value==null)return null;let w=(d=r.value.$el)!=null?d:r.value;return w instanceof Node?w:null}function Jn(r,d,...w){if(r in d){let x=d[r];return typeof x=="function"?x(...w):x}let t=new Error(`Tried to handle "${r}" but there is no handler defined. Only defined handlers are: ${Object.keys(d).map(x=>`"${x}"`).join(", ")}.`);throw Error.captureStackTrace&&Error.captureStackTrace(t,Jn),t}var p1=Object.defineProperty,m1=(r,d,w)=>d in r?p1(r,d,{enumerable:!0,configurable:!0,writable:!0,value:w}):r[d]=w,Rc=(r,d,w)=>(m1(r,typeof d!="symbol"?d+"":d,w),w);let y1=class{constructor(){Rc(this,"current",this.detect()),Rc(this,"currentId",0)}set(d){this.current!==d&&(this.currentId=0,this.current=d)}reset(){this.set(this.detect())}nextId(){return++this.currentId}get isServer(){return this.current==="server"}get isClient(){return this.current==="client"}detect(){return typeof window>"u"||typeof document>"u"?"server":"client"}},bi=new y1;function _l(r){if(bi.isServer)return null;if(r instanceof Node)return r.ownerDocument;if(r!=null&&r.hasOwnProperty("value")){let d=Ft(r);if(d)return d.ownerDocument}return document}let Fa=["[contentEditable=true]","[tabindex]","a[href]","area[href]","button:not([disabled])","iframe","input:not([disabled])","select:not([disabled])","textarea:not([disabled])"].map(r=>`${r}:not([tabindex='-1'])`).join(",");var Na=(r=>(r[r.First=1]="First",r[r.Previous=2]="Previous",r[r.Next=4]="Next",r[r.Last=8]="Last",r[r.WrapAround=16]="WrapAround",r[r.NoScroll=32]="NoScroll",r))(Na||{}),g1=(r=>(r[r.Error=0]="Error",r[r.Overflow=1]="Overflow",r[r.Success=2]="Success",r[r.Underflow=3]="Underflow",r))(g1||{}),v1=(r=>(r[r.Previous=-1]="Previous",r[r.Next=1]="Next",r))(v1||{});function rh(r=document.body){return r==null?[]:Array.from(r.querySelectorAll(Fa)).sort((d,w)=>Math.sign((d.tabIndex||Number.MAX_SAFE_INTEGER)-(w.tabIndex||Number.MAX_SAFE_INTEGER)))}var wl=(r=>(r[r.Strict=0]="Strict",r[r.Loose=1]="Loose",r))(wl||{});function xl(r,d=0){var w;return r===((w=_l(r))==null?void 0:w.body)?!1:Jn(d,{0(){return r.matches(Fa)},1(){let t=r;for(;t!==null;){if(t.matches(Fa))return!0;t=t.parentElement}return!1}})}function nh(r){let d=_l(r);Ur(()=>{d&&!xl(d.activeElement,0)&&_1(r)})}var b1=(r=>(r[r.Keyboard=0]="Keyboard",r[r.Mouse=1]="Mouse",r))(b1||{});typeof window<"u"&&typeof document<"u"&&(document.addEventListener("keydown",r=>{r.metaKey||r.altKey||r.ctrlKey||(document.documentElement.dataset.headlessuiFocusVisible="")},!0),document.addEventListener("click",r=>{r.detail===1?delete document.documentElement.dataset.headlessuiFocusVisible:r.detail===0&&(document.documentElement.dataset.headlessuiFocusVisible="")},!0));function _1(r){r==null||r.focus({preventScroll:!0})}let w1=["textarea","input"].join(",");function x1(r){var d,w;return(w=(d=r==null?void 0:r.matches)==null?void 0:d.call(r,w1))!=null?w:!1}function oh(r,d=w=>w){return r.slice().sort((w,t)=>{let x=d(w),v=d(t);if(x===null||v===null)return 0;let s=x.compareDocumentPosition(v);return s&Node.DOCUMENT_POSITION_FOLLOWING?-1:s&Node.DOCUMENT_POSITION_PRECEDING?1:0})}function j1(r,d){return S1(rh(),d,{relativeTo:r})}function S1(r,d,{sorted:w=!0,relativeTo:t=null,skipElements:x=[]}={}){var v;let s=(v=Array.isArray(r)?r.length>0?r[0].ownerDocument:document:r==null?void 0:r.ownerDocument)!=null?v:document,u=Array.isArray(r)?w?oh(r):r:rh(r);x.length>0&&u.length>1&&(u=u.filter(a=>!x.includes(a))),t=t??s.activeElement;let o=(()=>{if(d&5)return 1;if(d&10)return-1;throw new Error("Missing Focus.First, Focus.Previous, Focus.Next or Focus.Last")})(),c=(()=>{if(d&1)return 0;if(d&2)return Math.max(0,u.indexOf(t))-1;if(d&4)return Math.max(0,u.indexOf(t))+1;if(d&8)return u.length-1;throw new Error("Missing Focus.First, Focus.Previous, Focus.Next or Focus.Last")})(),g=d&32?{preventScroll:!0}:{},p=0,n=u.length,i;do{if(p>=n||p+n<=0)return 0;let a=c+p;if(d&16)a=(a+n)%n;else{if(a<0)return 3;if(a>=n)return 1}i=u[a],i==null||i.focus(g),p+=o}while(i!==s.activeElement);return d&6&&x1(i)&&i.select(),2}function E1(){return/iPhone/gi.test(window.navigator.platform)||/Mac/gi.test(window.navigator.platform)&&window.navigator.maxTouchPoints>0}function T1(){return/Android/gi.test(window.navigator.userAgent)}function M1(){return E1()||T1()}function Ls(r,d,w){bi.isServer||ln(t=>{document.addEventListener(r,d,w),t(()=>document.removeEventListener(r,d,w))})}function k1(r,d,w){bi.isServer||ln(t=>{window.addEventListener(r,d,w),t(()=>window.removeEventListener(r,d,w))})}function C1(r,d,w=jt(()=>!0)){function t(v,s){if(!w.value||v.defaultPrevented)return;let u=s(v);if(u===null||!u.getRootNode().contains(u))return;let o=function c(g){return typeof g=="function"?c(g()):Array.isArray(g)||g instanceof Set?g:[g]}(r);for(let c of o){if(c===null)continue;let g=c instanceof HTMLElement?c:Ft(c);if(g!=null&&g.contains(u)||v.composed&&v.composedPath().includes(g))return}return!xl(u,wl.Loose)&&u.tabIndex!==-1&&v.preventDefault(),d(v,u)}let x=mt(null);Ls("pointerdown",v=>{var s,u;w.value&&(x.value=((u=(s=v.composedPath)==null?void 0:s.call(v))==null?void 0:u[0])||v.target)},!0),Ls("mousedown",v=>{var s,u;w.value&&(x.value=((u=(s=v.composedPath)==null?void 0:s.call(v))==null?void 0:u[0])||v.target)},!0),Ls("click",v=>{M1()||x.value&&(t(v,()=>x.value),x.value=null)},!0),Ls("touchend",v=>t(v,()=>v.target instanceof HTMLElement?v.target:null),!0),k1("blur",v=>t(v,()=>window.document.activeElement instanceof HTMLIFrameElement?window.document.activeElement:null),!0)}function Lc(r,d){if(r)return r;let w=d??"button";if(typeof w=="string"&&w.toLowerCase()==="button")return"button"}function O1(r,d){let w=mt(Lc(r.value.type,r.value.as));return Qr(()=>{w.value=Lc(r.value.type,r.value.as)}),ln(()=>{var t;w.value||Ft(d)&&Ft(d)instanceof HTMLButtonElement&&!((t=Ft(d))!=null&&t.hasAttribute("type"))&&(w.value="button")}),w}let Ic=/([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g;function Dc(r){var d,w;let t=(d=r.innerText)!=null?d:"",x=r.cloneNode(!0);if(!(x instanceof HTMLElement))return t;let v=!1;for(let u of x.querySelectorAll('[hidden],[aria-hidden],[role="img"]'))u.remove(),v=!0;let s=v?(w=x.innerText)!=null?w:"":t;return Ic.test(s)&&(s=s.replace(Ic,"")),s}function P1(r){let d=r.getAttribute("aria-label");if(typeof d=="string")return d.trim();let w=r.getAttribute("aria-labelledby");if(w){let t=w.split(" ").map(x=>{let v=document.getElementById(x);if(v){let s=v.getAttribute("aria-label");return typeof s=="string"?s.trim():Dc(v).trim()}return null}).filter(Boolean);if(t.length>0)return t.join(", ")}return Dc(r).trim()}function A1(r){let d=mt(""),w=mt("");return()=>{let t=Ft(r);if(!t)return"";let x=t.innerText;if(d.value===x)return w.value;let v=P1(t).trim().toLowerCase();return d.value=x,w.value=v,v}}function Fc(r){return[r.screenX,r.screenY]}function R1(){let r=mt([-1,-1]);return{wasMoved(d){let w=Fc(d);return r.value[0]===w[0]&&r.value[1]===w[1]?!1:(r.value=w,!0)},update(d){r.value=Fc(d)}}}function L1({container:r,accept:d,walk:w,enabled:t}){ln(()=>{let x=r.value;if(!x||t!==void 0&&!t.value)return;let v=_l(r);if(!v)return;let s=Object.assign(o=>d(o),{acceptNode:d}),u=v.createTreeWalker(x,NodeFilter.SHOW_ELEMENT,s,!1);for(;u.nextNode();)w(u.currentNode)})}let sh=Symbol("Context");var Dr=(r=>(r[r.Open=1]="Open",r[r.Closed=2]="Closed",r[r.Closing=4]="Closing",r[r.Opening=8]="Opening",r))(Dr||{});function I1(){return jl()!==null}function jl(){return Ht(sh,null)}function ih(r){Wr(sh,r)}var ir=(r=>(r.Space=" ",r.Enter="Enter",r.Escape="Escape",r.Backspace="Backspace",r.Delete="Delete",r.ArrowLeft="ArrowLeft",r.ArrowUp="ArrowUp",r.ArrowRight="ArrowRight",r.ArrowDown="ArrowDown",r.Home="Home",r.End="End",r.PageUp="PageUp",r.PageDown="PageDown",r.Tab="Tab",r))(ir||{});function D1(r){throw new Error("Unexpected object: "+r)}var Nr=(r=>(r[r.First=0]="First",r[r.Previous=1]="Previous",r[r.Next=2]="Next",r[r.Last=3]="Last",r[r.Specific=4]="Specific",r[r.Nothing=5]="Nothing",r))(Nr||{});function F1(r,d){let w=d.resolveItems();if(w.length<=0)return null;let t=d.resolveActiveIndex(),x=t??-1;switch(r.focus){case 0:{for(let v=0;v=0;--v)if(!d.resolveDisabled(w[v],v,w))return v;return t}case 2:{for(let v=x+1;v=0;--v)if(!d.resolveDisabled(w[v],v,w))return v;return t}case 4:{for(let v=0;v(r[r.None=0]="None",r[r.RenderStrategy=1]="RenderStrategy",r[r.Static=2]="Static",r))(ri||{}),An=(r=>(r[r.Unmount=0]="Unmount",r[r.Hidden=1]="Hidden",r))(An||{});function Eo({visible:r=!0,features:d=0,ourProps:w,theirProps:t,...x}){var v;let s=lh(t,w),u=Object.assign(x,{props:s});if(r||d&2&&s.static)return ra(u);if(d&1){let o=(v=s.unmount)==null||v?0:1;return Jn(o,{0(){return null},1(){return ra({...x,props:{...s,hidden:!0,style:{display:"none"}}})}})}return ra(u)}function ra({props:r,attrs:d,slots:w,slot:t,name:x}){var v,s;let{as:u,...o}=uh(r,["unmount","static"]),c=(v=w.default)==null?void 0:v.call(w,t),g={};if(t){let p=!1,n=[];for(let[i,a]of Object.entries(t))typeof a=="boolean"&&(p=!0),a===!0&&n.push(i);p&&(g["data-headlessui-state"]=n.join(" "))}if(u==="template"){if(c=ah(c??[]),Object.keys(o).length>0||Object.keys(d).length>0){let[p,...n]=c??[];if(!N1(p)||n.length>0)throw new Error(['Passing props on "template"!',"",`The current component <${x} /> is rendering a "template".`,"However we need to passthrough the following props:",Object.keys(o).concat(Object.keys(d)).map(h=>h.trim()).filter((h,y,l)=>l.indexOf(h)===y).sort((h,y)=>h.localeCompare(y)).map(h=>` - ${h}`).join(` +`),"","You can apply a few solutions:",['Add an `as="..."` prop, to ensure that we render an actual element instead of a "template".',"Render a single element as the child so that we can forward the props onto that element."].map(h=>` - ${h}`).join(` +`)].join(` +`));let i=lh((s=p.props)!=null?s:{},o,g),a=un(p,i,!0);for(let h in i)h.startsWith("on")&&(a.props||(a.props={}),a.props[h]=i[h]);return a}return Array.isArray(c)&&c.length===1?c[0]:c}return tr(u,Object.assign({},o,g),{default:()=>c})}function ah(r){return r.flatMap(d=>d.type===yr?ah(d.children):[d])}function lh(...r){if(r.length===0)return{};if(r.length===1)return r[0];let d={},w={};for(let t of r)for(let x in t)x.startsWith("on")&&typeof t[x]=="function"?(w[x]!=null||(w[x]=[]),w[x].push(t[x])):d[x]=t[x];if(d.disabled||d["aria-disabled"])return Object.assign(d,Object.fromEntries(Object.keys(w).map(t=>[t,void 0])));for(let t in w)Object.assign(d,{[t](x,...v){let s=w[t];for(let u of s){if(x instanceof Event&&x.defaultPrevented)return;u(x,...v)}}});return d}function uh(r,d=[]){let w=Object.assign({},r);for(let t of d)t in w&&delete w[t];return w}function N1(r){return r==null?!1:typeof r.type=="string"||typeof r.type=="object"||typeof r.type=="function"}var U1=(r=>(r[r.Open=0]="Open",r[r.Closed=1]="Closed",r))(U1||{}),B1=(r=>(r[r.Pointer=0]="Pointer",r[r.Other=1]="Other",r))(B1||{});function G1(r){requestAnimationFrame(()=>requestAnimationFrame(r))}let ch=Symbol("MenuContext");function _i(r){let d=Ht(ch,null);if(d===null){let w=new Error(`<${r} /> is missing a parent component.`);throw Error.captureStackTrace&&Error.captureStackTrace(w,_i),w}return d}let V1=hr({name:"Menu",props:{as:{type:[Object,String],default:"template"}},setup(r,{slots:d,attrs:w}){let t=mt(1),x=mt(null),v=mt(null),s=mt([]),u=mt(""),o=mt(null),c=mt(1);function g(n=i=>i){let i=o.value!==null?s.value[o.value]:null,a=oh(n(s.value.slice()),y=>Ft(y.dataRef.domRef)),h=i?a.indexOf(i):null;return h===-1&&(h=null),{items:a,activeItemIndex:h}}let p={menuState:t,buttonRef:x,itemsRef:v,items:s,searchQuery:u,activeItemIndex:o,activationTrigger:c,closeMenu:()=>{t.value=1,o.value=null},openMenu:()=>t.value=0,goToItem(n,i,a){let h=g(),y=F1(n===Nr.Specific?{focus:Nr.Specific,id:i}:{focus:n},{resolveItems:()=>h.items,resolveActiveIndex:()=>h.activeItemIndex,resolveId:l=>l.id,resolveDisabled:l=>l.dataRef.disabled});u.value="",o.value=y,c.value=a??1,s.value=h.items},search(n){let i=u.value!==""?0:1;u.value+=n.toLowerCase();let a=(o.value!==null?s.value.slice(o.value+i).concat(s.value.slice(0,o.value+i)):s.value).find(y=>y.dataRef.textValue.startsWith(u.value)&&!y.dataRef.disabled),h=a?s.value.indexOf(a):-1;h===-1||h===o.value||(o.value=h,c.value=1)},clearSearch(){u.value=""},registerItem(n,i){let a=g(h=>[...h,{id:n,dataRef:i}]);s.value=a.items,o.value=a.activeItemIndex,c.value=1},unregisterItem(n){let i=g(a=>{let h=a.findIndex(y=>y.id===n);return h!==-1&&a.splice(h,1),a});s.value=i.items,o.value=i.activeItemIndex,c.value=1}};return C1([x,v],(n,i)=>{var a;p.closeMenu(),xl(i,wl.Loose)||(n.preventDefault(),(a=Ft(x))==null||a.focus())},jt(()=>t.value===0)),Wr(ch,p),ih(jt(()=>Jn(t.value,{0:Dr.Open,1:Dr.Closed}))),()=>{let n={open:t.value===0,close:p.closeMenu};return Eo({ourProps:{},theirProps:r,slot:n,slots:d,attrs:w,name:"Menu"})}}}),H1=hr({name:"MenuButton",props:{disabled:{type:Boolean,default:!1},as:{type:[Object,String],default:"button"},id:{type:String,default:null}},setup(r,{attrs:d,slots:w,expose:t}){var x;let v=(x=r.id)!=null?x:`headlessui-menu-button-${vi()}`,s=_i("MenuButton");t({el:s.buttonRef,$el:s.buttonRef});function u(p){switch(p.key){case ir.Space:case ir.Enter:case ir.ArrowDown:p.preventDefault(),p.stopPropagation(),s.openMenu(),Ur(()=>{var n;(n=Ft(s.itemsRef))==null||n.focus({preventScroll:!0}),s.goToItem(Nr.First)});break;case ir.ArrowUp:p.preventDefault(),p.stopPropagation(),s.openMenu(),Ur(()=>{var n;(n=Ft(s.itemsRef))==null||n.focus({preventScroll:!0}),s.goToItem(Nr.Last)});break}}function o(p){switch(p.key){case ir.Space:p.preventDefault();break}}function c(p){r.disabled||(s.menuState.value===0?(s.closeMenu(),Ur(()=>{var n;return(n=Ft(s.buttonRef))==null?void 0:n.focus({preventScroll:!0})})):(p.preventDefault(),s.openMenu(),G1(()=>{var n;return(n=Ft(s.itemsRef))==null?void 0:n.focus({preventScroll:!0})})))}let g=O1(jt(()=>({as:r.as,type:d.type})),s.buttonRef);return()=>{var p;let n={open:s.menuState.value===0},{...i}=r,a={ref:s.buttonRef,id:v,type:g.value,"aria-haspopup":"menu","aria-controls":(p=Ft(s.itemsRef))==null?void 0:p.id,"aria-expanded":s.menuState.value===0,onKeydown:u,onKeyup:o,onClick:c};return Eo({ourProps:a,theirProps:i,slot:n,attrs:d,slots:w,name:"MenuButton"})}}}),z1=hr({name:"MenuItems",props:{as:{type:[Object,String],default:"div"},static:{type:Boolean,default:!1},unmount:{type:Boolean,default:!0},id:{type:String,default:null}},setup(r,{attrs:d,slots:w,expose:t}){var x;let v=(x=r.id)!=null?x:`headlessui-menu-items-${vi()}`,s=_i("MenuItems"),u=mt(null);t({el:s.itemsRef,$el:s.itemsRef}),L1({container:jt(()=>Ft(s.itemsRef)),enabled:jt(()=>s.menuState.value===0),accept(n){return n.getAttribute("role")==="menuitem"?NodeFilter.FILTER_REJECT:n.hasAttribute("role")?NodeFilter.FILTER_SKIP:NodeFilter.FILTER_ACCEPT},walk(n){n.setAttribute("role","none")}});function o(n){var i;switch(u.value&&clearTimeout(u.value),n.key){case ir.Space:if(s.searchQuery.value!=="")return n.preventDefault(),n.stopPropagation(),s.search(n.key);case ir.Enter:if(n.preventDefault(),n.stopPropagation(),s.activeItemIndex.value!==null){let a=s.items.value[s.activeItemIndex.value];(i=Ft(a.dataRef.domRef))==null||i.click()}s.closeMenu(),nh(Ft(s.buttonRef));break;case ir.ArrowDown:return n.preventDefault(),n.stopPropagation(),s.goToItem(Nr.Next);case ir.ArrowUp:return n.preventDefault(),n.stopPropagation(),s.goToItem(Nr.Previous);case ir.Home:case ir.PageUp:return n.preventDefault(),n.stopPropagation(),s.goToItem(Nr.First);case ir.End:case ir.PageDown:return n.preventDefault(),n.stopPropagation(),s.goToItem(Nr.Last);case ir.Escape:n.preventDefault(),n.stopPropagation(),s.closeMenu(),Ur(()=>{var a;return(a=Ft(s.buttonRef))==null?void 0:a.focus({preventScroll:!0})});break;case ir.Tab:n.preventDefault(),n.stopPropagation(),s.closeMenu(),Ur(()=>j1(Ft(s.buttonRef),n.shiftKey?Na.Previous:Na.Next));break;default:n.key.length===1&&(s.search(n.key),u.value=setTimeout(()=>s.clearSearch(),350));break}}function c(n){switch(n.key){case ir.Space:n.preventDefault();break}}let g=jl(),p=jt(()=>g!==null?(g.value&Dr.Open)===Dr.Open:s.menuState.value===0);return()=>{var n,i;let a={open:s.menuState.value===0},{...h}=r,y={"aria-activedescendant":s.activeItemIndex.value===null||(n=s.items.value[s.activeItemIndex.value])==null?void 0:n.id,"aria-labelledby":(i=Ft(s.buttonRef))==null?void 0:i.id,id:v,onKeydown:o,onKeyup:c,role:"menu",tabIndex:0,ref:s.itemsRef};return Eo({ourProps:y,theirProps:h,slot:a,attrs:d,slots:w,features:ri.RenderStrategy|ri.Static,visible:p.value,name:"MenuItems"})}}}),W1=hr({name:"MenuItem",inheritAttrs:!1,props:{as:{type:[Object,String],default:"template"},disabled:{type:Boolean,default:!1},id:{type:String,default:null}},setup(r,{slots:d,attrs:w,expose:t}){var x;let v=(x=r.id)!=null?x:`headlessui-menu-item-${vi()}`,s=_i("MenuItem"),u=mt(null);t({el:u,$el:u});let o=jt(()=>s.activeItemIndex.value!==null?s.items.value[s.activeItemIndex.value].id===v:!1),c=A1(u),g=jt(()=>({disabled:r.disabled,get textValue(){return c()},domRef:u}));Qr(()=>s.registerItem(v,g)),us(()=>s.unregisterItem(v)),ln(()=>{s.menuState.value===0&&o.value&&s.activationTrigger.value!==0&&Ur(()=>{var l,f;return(f=(l=Ft(u))==null?void 0:l.scrollIntoView)==null?void 0:f.call(l,{block:"nearest"})})});function p(l){if(r.disabled)return l.preventDefault();s.closeMenu(),nh(Ft(s.buttonRef))}function n(){if(r.disabled)return s.goToItem(Nr.Nothing);s.goToItem(Nr.Specific,v)}let i=R1();function a(l){i.update(l)}function h(l){i.wasMoved(l)&&(r.disabled||o.value||s.goToItem(Nr.Specific,v,0))}function y(l){i.wasMoved(l)&&(r.disabled||o.value&&s.goToItem(Nr.Nothing))}return()=>{let{disabled:l,...f}=r,m={active:o.value,disabled:l,close:s.closeMenu};return Eo({ourProps:{id:v,ref:u,role:"menuitem",tabIndex:l===!0?void 0:-1,"aria-disabled":l===!0?!0:void 0,onClick:p,onFocus:n,onPointerenter:a,onMouseenter:a,onPointermove:h,onMousemove:h,onPointerleave:y,onMouseleave:y},theirProps:{...w,...f},slot:m,attrs:w,slots:d,name:"MenuItem"})}}});function q1(r,d){return Fr(),cs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true","data-slot":"icon"},[Ct("path",{"fill-rule":"evenodd",d:"M2 4.75A.75.75 0 0 1 2.75 4h14.5a.75.75 0 0 1 0 1.5H2.75A.75.75 0 0 1 2 4.75ZM2 10a.75.75 0 0 1 .75-.75h14.5a.75.75 0 0 1 0 1.5H2.75A.75.75 0 0 1 2 10Zm0 5.25a.75.75 0 0 1 .75-.75h14.5a.75.75 0 0 1 0 1.5H2.75a.75.75 0 0 1-.75-.75Z","clip-rule":"evenodd"})])}const X1={class:"container mx-auto py-6"},Y1={class:"flex items-center text-gray-200"},$1={class:"flex items-center"},Z1=Ct("svg",{class:"mr-2 inline h-6 w-6 hover:text-orange-300",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor"},[Ct("path",{d:"M12.001 2C6.47598 2 2.00098 6.475 2.00098 12C2.00098 16.425 4.86348 20.1625 8.83848 21.4875C9.33848 21.575 9.52598 21.275 9.52598 21.0125C9.52598 20.775 9.51348 19.9875 9.51348 19.15C7.00098 19.6125 6.35098 18.5375 6.15098 17.975C6.03848 17.6875 5.55098 16.8 5.12598 16.5625C4.77598 16.375 4.27598 15.9125 5.11348 15.9C5.90098 15.8875 6.46348 16.625 6.65098 16.925C7.55098 18.4375 8.98848 18.0125 9.56348 17.75C9.65098 17.1 9.91348 16.6625 10.201 16.4125C7.97598 16.1625 5.65098 15.3 5.65098 11.475C5.65098 10.3875 6.03848 9.4875 6.67598 8.7875C6.57598 8.5375 6.22598 7.5125 6.77598 6.1375C6.77598 6.1375 7.61348 5.875 9.52598 7.1625C10.326 6.9375 11.176 6.825 12.026 6.825C12.876 6.825 13.726 6.9375 14.526 7.1625C16.4385 5.8625 17.276 6.1375 17.276 6.1375C17.826 7.5125 17.476 8.5375 17.376 8.7875C18.0135 9.4875 18.401 10.375 18.401 11.475C18.401 15.3125 16.0635 16.1625 13.8385 16.4125C14.201 16.725 14.5135 17.325 14.5135 18.2625C14.5135 19.6 14.501 20.675 14.501 21.0125C14.501 21.275 14.6885 21.5875 15.1885 21.4875C19.259 20.1133 21.9999 16.2963 22.001 12C22.001 6.475 17.526 2 12.001 2Z"})],-1),K1={class:"px-1 py-1"},Q1={href:"/articles"},J1=Ct("svg",{class:"mr-2 inline h-5 w-5",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor"},[Ct("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10"})],-1),e_={href:"/talks"},t_=Ct("svg",{class:"mr-2 inline h-5 w-5",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor"},[Ct("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M3.75 3v11.25A2.25 2.25 0 0 0 6 16.5h2.25M3.75 3h-1.5m1.5 0h16.5m0 0h1.5m-1.5 0v11.25A2.25 2.25 0 0 1 18 16.5h-2.25m-7.5 0h7.5m-7.5 0-1 3m8.5-3 1 3m0 0 .5 1.5m-.5-1.5h-9.5m0 0-.5 1.5M9 11.25v1.5M12 9v3.75m3-6v6"})],-1),r_={href:"/playground"},n_=Ct("svg",{class:"mr-2 inline h-5 w-5",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor"},[Ct("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M9.75 3.104v5.714a2.25 2.25 0 01-.659 1.591L5 14.5M9.75 3.104c-.251.023-.501.05-.75.082m.75-.082a24.301 24.301 0 014.5 0m0 0v5.714c0 .597.237 1.17.659 1.591L19.8 15.3M14.25 3.104c.251.023.501.05.75.082M19.8 15.3l-1.57.393A9.065 9.065 0 0112 15a9.065 9.065 0 00-6.23-.693L5 14.5m14.8.8l1.402 1.402c1.232 1.232.65 3.318-1.067 3.611A48.309 48.309 0 0112 21c-2.773 0-5.491-.235-8.135-.687-1.718-.293-2.3-2.379-1.067-3.61L5 14.5"})],-1),o_={__name:"Header",setup(r){return hi(),(d,w)=>{const t=i1,x=u1,v=H1,s=W1,u=z1,o=V1;return Fr(),cs("nav",X1,[Ct("div",Y1,[ft(x,{to:"/",class:"flex-1"},{default:Ir(()=>[ft(t,{class:"w-32 md:w-64"})]),_:1}),Ct("div",$1,[ft(x,{to:"https://github.com/cmpadden"},{default:Ir(()=>[Z1]),_:1}),ft(o,{as:"div",class:"relative z-50 inline-block text-left"},{default:Ir(()=>[Ct("div",null,[ft(v,{class:"inline-flex w-full justify-center rounded-md bg-black/50 p-2 text-sm font-medium text-white hover:bg-opacity-30 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75"},{default:Ir(()=>[ft(Bt(q1),{class:"h-5 w-5 text-white hover:text-orange-500","aria-hidden":"true"})]),_:1})]),ft(fs,{"enter-active-class":"transition duration-100 ease-out","enter-from-class":"transform scale-95 opacity-0","enter-to-class":"transform scale-100 opacity-100","leave-active-class":"transition duration-75 ease-in","leave-from-class":"transform scale-100 opacity-100","leave-to-class":"transform scale-95 opacity-0"},{default:Ir(()=>[ft(u,{class:"absolute right-0 mt-2 w-56 origin-top-right divide-y divide-gray-100 rounded-md bg-black/80 text-white shadow-lg ring-1 ring-black ring-opacity-5 backdrop-blur-sm focus:outline-none"},{default:Ir(()=>[Ct("div",K1,[ft(s,null,{default:Ir(({active:c})=>[Ct("a",Q1,[Ct("button",{class:Yn([c?"bg-slate-700 text-white":"text-white","group flex w-full items-center rounded-md px-2 py-2 text-sm"])},[J1,zo(" Blog ")],2)])]),_:1}),ft(s,null,{default:Ir(({active:c})=>[Ct("a",e_,[Ct("button",{class:Yn([c?"bg-slate-700":"","group flex w-full items-center rounded-md px-2 py-2 text-sm"])},[t_,zo(" Talks ")],2)])]),_:1}),ft(s,null,{default:Ir(({active:c})=>[Ct("a",r_,[Ct("button",{class:Yn([c?"bg-slate-700 text-white":"text-white","group flex w-full items-center rounded-md px-2 py-2 text-sm"])},[n_,zo(" Experiments ")],2)])]),_:1})])]),_:1})]),_:1})]),_:1})])])])}}};function s_(r){typeof queueMicrotask=="function"?queueMicrotask(r):Promise.resolve().then(r).catch(d=>setTimeout(()=>{throw d}))}function Sl(){let r=[],d={addEventListener(w,t,x,v){return w.addEventListener(t,x,v),d.add(()=>w.removeEventListener(t,x,v))},requestAnimationFrame(...w){let t=requestAnimationFrame(...w);d.add(()=>cancelAnimationFrame(t))},nextFrame(...w){d.requestAnimationFrame(()=>{d.requestAnimationFrame(...w)})},setTimeout(...w){let t=setTimeout(...w);d.add(()=>clearTimeout(t))},microTask(...w){let t={current:!0};return s_(()=>{t.current&&w[0]()}),d.add(()=>{t.current=!1})},style(w,t,x){let v=w.style.getPropertyValue(t);return Object.assign(w.style,{[t]:x}),this.add(()=>{Object.assign(w.style,{[t]:v})})},group(w){let t=Sl();return w(t),this.add(()=>t.dispose())},add(w){return r.push(w),()=>{let t=r.indexOf(w);if(t>=0)for(let x of r.splice(t,1))x()}},dispose(){for(let w of r.splice(0))w()}};return d}function i_(r){let d={called:!1};return(...w)=>{if(!d.called)return d.called=!0,r(...w)}}function na(r,...d){r&&d.length>0&&r.classList.add(...d)}function Is(r,...d){r&&d.length>0&&r.classList.remove(...d)}var Ua=(r=>(r.Finished="finished",r.Cancelled="cancelled",r))(Ua||{});function a_(r,d){let w=Sl();if(!r)return w.dispose;let{transitionDuration:t,transitionDelay:x}=getComputedStyle(r),[v,s]=[t,x].map(u=>{let[o=0]=u.split(",").filter(Boolean).map(c=>c.includes("ms")?parseFloat(c):parseFloat(c)*1e3).sort((c,g)=>g-c);return o});return v!==0?w.setTimeout(()=>d("finished"),v+s):d("finished"),w.add(()=>d("cancelled")),w.dispose}function Nc(r,d,w,t,x,v){let s=Sl(),u=v!==void 0?i_(v):()=>{};return Is(r,...x),na(r,...d,...w),s.nextFrame(()=>{Is(r,...w),na(r,...t),s.add(a_(r,o=>(Is(r,...t,...d),na(r,...x),u(o))))}),s.add(()=>Is(r,...d,...w,...t,...x)),s.add(()=>u("cancelled")),s.dispose}function Hn(r=""){return r.split(/\s+/).filter(d=>d.length>1)}let El=Symbol("TransitionContext");var l_=(r=>(r.Visible="visible",r.Hidden="hidden",r))(l_||{});function u_(){return Ht(El,null)!==null}function c_(){let r=Ht(El,null);if(r===null)throw new Error("A is used but it is missing a parent .");return r}function d_(){let r=Ht(Tl,null);if(r===null)throw new Error("A is used but it is missing a parent .");return r}let Tl=Symbol("NestingContext");function wi(r){return"children"in r?wi(r.children):r.value.filter(({state:d})=>d==="visible").length>0}function dh(r){let d=mt([]),w=mt(!1);Qr(()=>w.value=!0),us(()=>w.value=!1);function t(v,s=An.Hidden){let u=d.value.findIndex(({id:o})=>o===v);u!==-1&&(Jn(s,{[An.Unmount](){d.value.splice(u,1)},[An.Hidden](){d.value[u].state="hidden"}}),!wi(d)&&w.value&&(r==null||r()))}function x(v){let s=d.value.find(({id:u})=>u===v);return s?s.state!=="visible"&&(s.state="visible"):d.value.push({id:v,state:"visible"}),()=>t(v,An.Unmount)}return{children:d,register:x,unregister:t}}let fh=ri.RenderStrategy,f_=hr({props:{as:{type:[Object,String],default:"div"},show:{type:[Boolean],default:null},unmount:{type:[Boolean],default:!0},appear:{type:[Boolean],default:!1},enter:{type:[String],default:""},enterFrom:{type:[String],default:""},enterTo:{type:[String],default:""},entered:{type:[String],default:""},leave:{type:[String],default:""},leaveFrom:{type:[String],default:""},leaveTo:{type:[String],default:""}},emits:{beforeEnter:()=>!0,afterEnter:()=>!0,beforeLeave:()=>!0,afterLeave:()=>!0},setup(r,{emit:d,attrs:w,slots:t,expose:x}){let v=mt(0);function s(){v.value|=Dr.Opening,d("beforeEnter")}function u(){v.value&=~Dr.Opening,d("afterEnter")}function o(){v.value|=Dr.Closing,d("beforeLeave")}function c(){v.value&=~Dr.Closing,d("afterLeave")}if(!u_()&&I1())return()=>tr(hh,{...r,onBeforeEnter:s,onAfterEnter:u,onBeforeLeave:o,onAfterLeave:c},t);let g=mt(null),p=jt(()=>r.unmount?An.Unmount:An.Hidden);x({el:g,$el:g});let{show:n,appear:i}=c_(),{register:a,unregister:h}=d_(),y=mt(n.value?"visible":"hidden"),l={value:!0},f=vi(),m={value:!1},b=dh(()=>{!m.value&&y.value!=="hidden"&&(y.value="hidden",h(f),c())});Qr(()=>{let A=a(f);us(A)}),ln(()=>{if(p.value===An.Hidden&&f){if(n.value&&y.value!=="visible"){y.value="visible";return}Jn(y.value,{hidden:()=>h(f),visible:()=>a(f)})}});let j=Hn(r.enter),M=Hn(r.enterFrom),E=Hn(r.enterTo),k=Hn(r.entered),P=Hn(r.leave),L=Hn(r.leaveFrom),C=Hn(r.leaveTo);Qr(()=>{ln(()=>{if(y.value==="visible"){let A=Ft(g);if(A instanceof Comment&&A.data==="")throw new Error("Did you forget to passthrough the `ref` to the actual DOM node?")}})});function I(A){let N=l.value&&!i.value,F=Ft(g);!F||!(F instanceof HTMLElement)||N||(m.value=!0,n.value&&s(),n.value||o(),A(n.value?Nc(F,j,M,E,k,B=>{m.value=!1,B===Ua.Finished&&u()}):Nc(F,P,L,C,k,B=>{m.value=!1,B===Ua.Finished&&(wi(b)||(y.value="hidden",h(f),c()))})))}return Qr(()=>{In([n],(A,N,F)=>{I(F),l.value=!1},{immediate:!0})}),Wr(Tl,b),ih(jt(()=>Jn(y.value,{visible:Dr.Open,hidden:Dr.Closed})|v.value)),()=>{let{appear:A,show:N,enter:F,enterFrom:B,enterTo:q,entered:V,leave:H,leaveFrom:K,leaveTo:ee,...ue}=r,T={ref:g},D={...ue,...i.value&&n.value&&bi.isServer?{class:Yn([w.class,ue.class,...j,...M])}:{}};return Eo({theirProps:D,ourProps:T,slot:{},slots:t,attrs:w,features:fh,visible:y.value==="visible",name:"TransitionChild"})}}}),h_=f_,hh=hr({inheritAttrs:!1,props:{as:{type:[Object,String],default:"div"},show:{type:[Boolean],default:null},unmount:{type:[Boolean],default:!0},appear:{type:[Boolean],default:!1},enter:{type:[String],default:""},enterFrom:{type:[String],default:""},enterTo:{type:[String],default:""},entered:{type:[String],default:""},leave:{type:[String],default:""},leaveFrom:{type:[String],default:""},leaveTo:{type:[String],default:""}},emits:{beforeEnter:()=>!0,afterEnter:()=>!0,beforeLeave:()=>!0,afterLeave:()=>!0},setup(r,{emit:d,attrs:w,slots:t}){let x=jl(),v=jt(()=>r.show===null&&x!==null?(x.value&Dr.Open)===Dr.Open:r.show);ln(()=>{if(![!0,!1].includes(v.value))throw new Error('A is used but it is missing a `:show="true | false"` prop.')});let s=mt(v.value?"visible":"hidden"),u=dh(()=>{s.value="hidden"}),o=mt(!0),c={show:v,appear:jt(()=>r.appear||!o.value)};return Qr(()=>{ln(()=>{o.value=!1,v.value?s.value="visible":wi(u)||(s.value="hidden")})}),Wr(Tl,u),Wr(El,c),()=>{let g=uh(r,["show","appear","unmount","onBeforeEnter","onBeforeLeave","onAfterEnter","onAfterLeave"]),p={unmount:r.unmount};return Eo({ourProps:{...p,as:"template"},theirProps:{},slot:{},slots:{...t,default:()=>[tr(h_,{onBeforeEnter:()=>d("beforeEnter"),onAfterEnter:()=>d("afterEnter"),onBeforeLeave:()=>d("beforeLeave"),onAfterLeave:()=>d("afterLeave"),...w,...p,...g},t.default)]},attrs:{},features:fh,visible:s.value==="visible",name:"Transition"})}}});const p_={},m_={class:"flex min-h-screen flex-col bg-background font-display"},y_={class:"mt-4 flex-1"},g_={class:"flex justify-center"},v_=Ct("div",{class:"rounded-xl bg-black/50 p-6 text-center shadow-lg"},[Ct("div",{class:"text-6xl font-extrabold tracking-widest text-white"}," Yikes! "),Ct("div",{class:"text-base text-gray-200"}," Either the page you're looking for doesn't exist, or something has gone terribly wrong. ")],-1);function b_(r,d){const w=o_,t=hh;return Fr(),cs("body",m_,[ft(w),Ct("main",y_,[Ct("div",g_,[ft(t,{show:"",appear:"",as:"template",enter:"transition transform duration-300 ease-out","enter-from":"translate-x-8 opacity-0","enter-to":"translate-x-0 opacity-100",leave:"transition transform duration-300 ease-in","leave-from":"opacity-100","leave-to":"-translate-x-8 opacity-0"},{default:Ir(()=>[v_]),_:1})])])])}const __=eh(p_,[["render",b_]]),Uc={__name:"nuxt-root",setup(r){const d=()=>null,w=It(),t=w.deferHydration();if(w.isHydrating){const u=w.hooks.hookOnce("app:error",t);qr().beforeEach(u)}const x=!1;Wr(ps,hi()),w.hooks.callHookWith(u=>u.map(o=>o()),"vue:setup");const v=pi();Pd((u,o,c)=>{if(w.hooks.callHook("vue:error",u,o,c).catch(g=>console.error("[nuxt] Error in `vue:error` hook",g)),Tg(u)&&(u.fatal||u.unhandled))return w.runWithContext(()=>ao(u)),!1});const s=!1;return(u,o)=>(Fr(),qn(rl,{onResolve:Bt(t)},{default:Ir(()=>[Bt(v)?(Fr(),qn(Bt(__),{key:0,error:Bt(v)},null,8,["error"])):Bt(s)?(Fr(),qn(Bt(d),{key:1,context:Bt(s)},null,8,["context"])):Bt(x)?(Fr(),qn(Ap(Bt(x)),{key:2})):(Fr(),qn(Bt(e1),{key:3}))]),_:1},8,["onResolve"]))}};let Bc;{let r;Bc=async function(){var s,u;if(r)return r;const t=!!((s=window.__NUXT__)!=null&&s.serverRendered||((u=document.getElementById("__NUXT_DATA__"))==null?void 0:u.dataset.ssr)==="true")?sy(Uc):oy(Uc),x=cg({vueApp:t});async function v(o){await x.callHook("app:error",o),x.payload.error=x.payload.error||mi(o)}t.config.errorHandler=v;try{await fg(x,zb)}catch(o){v(o)}try{await x.hooks.callHook("app:created",t),await x.hooks.callHook("app:beforeMount",t),t.mount(k0),await x.hooks.callHook("app:mounted",t),await Ur()}catch(o){v(o)}return t.config.errorHandler===v&&(t.config.errorHandler=void 0),t},r=Bc().catch(d=>{throw console.error("Error while mounting app:",d),d})}export{mi as $,Un as A,L_ as B,T_ as C,A_ as D,fr as E,yr as F,Ur as G,_0 as H,fi as I,C_ as J,Ks as K,tr as L,rt as M,wp as N,It as O,E_ as P,Ay as Q,$u as R,hh as S,fs as T,di as U,ci as V,R_ as W,Zo as X,Yp as Y,x_ as Z,u1 as _,Bt as a,So as a0,Xh as a1,bt as a2,Pp as a3,go as a4,gr as a5,$s as a6,S_ as a7,k_ as a8,Wa as a9,o_ as aa,As as ab,Ct as b,cs as c,hr as d,qn as e,Ir as f,zo as g,P_ as h,ft as i,mt as j,jt as k,Yn as l,eh as m,Sg as n,Fr as o,xm as p,Qr as q,M_ as r,f_ as s,w_ as t,hi as u,In as v,O_ as w,ls as x,us as y,j_ as z}; diff --git a/_nuxt/Ml_4v_Rc.js b/_nuxt/Ml_4v_Rc.js deleted file mode 100644 index 762f464a..00000000 --- a/_nuxt/Ml_4v_Rc.js +++ /dev/null @@ -1 +0,0 @@ -import{m as l,j as c,c as d,i as a,f as n,b as e,t as f,S as m,o as p,s as u}from"./CZZfhpmp.js";const y={setup(){return{show:c(!1)}}},g={class:"bg-gradeint-to-r flex min-h-screen items-center justify-center from-blue-400 to-indigo-500"},h={class:"flex w-96 items-center space-x-4 rounded-2xl bg-white p-4 shadow-xl"},x={class:"absolute inset-x-0 top-0 my-4 flex w-full items-center justify-center"};function _(r,t,v,o,w,b){const s=u,i=m;return p(),d("div",g,[a(i,{as:"template",show:o.show,enter:"transition transform duration-300 ease-out","enter-from":"translate-x-4 opacity-0","enter-to":"translate-x-0 opacity-100",leave:"transition transform duration-300 ease-in","leave-from":"opacity-100","leave-to":"opacity-0"},{default:n(()=>[e("div",h,[a(s,{as:"img",enter:"transition transform duration-300 ease-out","enter-from":"rotate-90 scale-50 opacity-0","enter-to":"rotate-0 scale-100 opacity-100",leave:"transition transform duration-300 ease-in","leave-from":"opacity-100","leave-to":"opacity-0",class:"h-16 w-16 rounded-full ring ring-indigo-500 ring-opacity-50 ring-offset-2",src:"/images/placeholder.png"}),a(s,{enter:"transition transform duration-300 ease-out","enter-from":"translate-x-12 opacity-0","enter-to":"translate-x-0 opacity-100",leave:"transition transform duration-300 ease-in","leave-from":"opacity-100","leave-to":"opacity-0"},{default:n(()=>t[1]||(t[1]=[e("h1",{class:"font-medium text-gray-900"},"Floofy McFloof",-1),e("p",{class:"mt-0.5 text-gray-500"}," Hey! I'm McFloof and I have been a very good boi this year. ",-1)])),_:1})])]),_:1},8,["show"]),e("div",x,[e("button",{class:"rounded-lg bg-blue-200 px-4 py-1.5 text-sm font-medium text-indigo-900 hover:bg-blue-100 focus:outline-none focus:ring-2 focus:ring-indigo-600",onClick:t[0]||(t[0]=H=>o.show=!o.show)},f(o.show?"Hide":"Show")+" profile ",1)])])}const j=l(y,[["render",_]]);export{j as default}; diff --git a/_nuxt/BDlA7Zky.js b/_nuxt/N3o-VwNZ.js similarity index 64% rename from _nuxt/BDlA7Zky.js rename to _nuxt/N3o-VwNZ.js index b9324de7..99d9e2d2 100644 --- a/_nuxt/BDlA7Zky.js +++ b/_nuxt/N3o-VwNZ.js @@ -1 +1 @@ -import{m as o,o as r,c as s,a8 as t}from"./CZZfhpmp.js";const c={};function n(e,a){return r(),s("ol",null,[t(e.$slots,"default")])}const f=o(c,[["render",n]]);export{f as default}; +import{m as o,o as r,c as s,a8 as t}from"./K1dcBiIN.js";const c={};function n(e,a){return r(),s("ol",null,[t(e.$slots,"default")])}const f=o(c,[["render",n]]);export{f as default}; diff --git a/_nuxt/NnUIAPGH.js b/_nuxt/NnUIAPGH.js new file mode 100644 index 00000000..7119e427 --- /dev/null +++ b/_nuxt/NnUIAPGH.js @@ -0,0 +1 @@ +import{j as S,a1 as T,Z as E,v as C,a7 as A,a6 as O,G as P,u as h}from"./K1dcBiIN.js";import{i as I}from"./DvDH6DOc.js";const m=/^[\u0009\u0020-\u007E\u0080-\u00FF]+$/;function R(e,i){if(typeof e!="string")throw new TypeError("argument str must be a string");const o={},a=(i||{}).decode||N;let s=0;for(;sO(decodeURIComponent(e)),encode:e=>encodeURIComponent(typeof e=="string"?e:JSON.stringify(e))},U=void 0;function y(e,i){var f;const o={...L,...i},t=b(o)||{};let a;o.maxAge!==void 0?a=o.maxAge*1e3:o.expires&&(a=o.expires.getTime()-Date.now());const s=a!==void 0&&a<=0,r=u(s?void 0:t[e]??((f=o.default)==null?void 0:f.call(o))),n=a&&!s?B(r,a,o.watch&&o.watch!=="shallow"):S(r);{let c=null;try{!U&&typeof BroadcastChannel<"u"&&(c=new BroadcastChannel(`nuxt:cookies:${e}`))}catch{}const l=()=>{o.readonly||I(n.value,t[e])||(q(e,n.value,o),t[e]=u(n.value),c==null||c.postMessage({value:o.encode(n.value)}))},p=w=>{var v;const j=w.refresh?(v=b(o))==null?void 0:v[e]:o.decode(w.value);d=!0,t[e]=n.value=j,P(()=>{d=!1})};let d=!1;T()&&E(()=>{d=!0,l(),c==null||c.close()}),c&&(c.onmessage=({data:w})=>p(w)),o.watch?C(n,()=>{d||l()},{deep:o.watch!=="shallow"}):l()}return n}function b(e={}){return R(document.cookie,e)}function _(e,i,o={}){return i==null?g(e,i,{...o,maxAge:-1}):g(e,i,o)}function q(e,i,o={}){document.cookie=_(e,i,o)}const k=2147483647;function B(e,i,o){let t,a,s=0;const r=o?S(e):{value:e};return T()&&E(()=>{a==null||a(),clearTimeout(t)}),A((n,f)=>{o&&(a=C(r,f));function c(){clearTimeout(t);const l=i-s,p=l{if(s+=p,s({isEnabled:()=>{const t=h().query;return Object.prototype.hasOwnProperty.call(t,"preview")&&!t.preview?!1:!!(t.preview||y("previewToken").value||sessionStorage.getItem("previewToken"))},getPreviewToken:()=>y("previewToken").value||sessionStorage.getItem("previewToken")||void 0,setPreviewToken:t=>{y("previewToken").value=t,h().query.preview=t||"",t?sessionStorage.setItem("previewToken",t):sessionStorage.removeItem("previewToken"),window.location.reload()}});export{z as u}; diff --git a/_nuxt/OorYyVAq.js b/_nuxt/OorYyVAq.js new file mode 100644 index 00000000..bca62679 --- /dev/null +++ b/_nuxt/OorYyVAq.js @@ -0,0 +1 @@ +import{k as C,z as _,A as E,B as O,d as R,j as N,w as U,v as V,o as r,c as n,b as o,a,F as y,C as q,D as I,E as K,r as k,g as B,t as x,h as S}from"./K1dcBiIN.js";import{h as W}from"./DvDH6DOc.js";import{u as M}from"./C6WZwVE2.js";function G(h,l,v){const[e={},c]=typeof l=="string"?[{},l]:[l,v],s=C(()=>_(h)),t=e.key||W([c,typeof s.value=="string"?s.value:"",...H(e)]);if(!t||typeof t!="string")throw new TypeError("[nuxt] [useFetch] key must be a string: "+t);const d=t===c?"$f"+t:t;if(!e.baseURL&&typeof s.value=="string"&&s.value[0]==="/"&&s.value[1]==="/")throw new Error('[nuxt] [useFetch] the request URL must not start with "//".');const{server:m,lazy:w,default:j,transform:D,pick:F,watch:u,immediate:p,getCachedData:i,deep:g,dedupe:L,...$}=e,b=E({...O,...$,cache:typeof e.cache=="boolean"?void 0:e.cache}),A={server:m,lazy:w,default:j,transform:D,pick:F,immediate:p,getCachedData:i,deep:g,dedupe:L,watch:u===!1?[]:[b,s,...u||[]]};let f;return M(d,()=>{var z;(z=f==null?void 0:f.abort)==null||z.call(f),f=typeof AbortController<"u"?new AbortController:{};const T=_(e.timeout);return T&&setTimeout(()=>f.abort(),T),(e.$fetch||globalThis.$fetch)(s.value,{signal:f.signal,...b})},A)}function H(h){var v;const l=[((v=_(h.method))==null?void 0:v.toUpperCase())||"GET",_(h.baseURL)];for(const e of[h.params||h.query]){const c=_(e);if(!c)continue;const s={};for(const[t,d]of Object.entries(c))s[_(t)]=_(d);l.push(s)}return l}const P={class:"flex h-screen flex-col font-mono"},Q={class:"flex flex-1 overflow-hidden"},J=o("div",{class:"flex w-20 bg-amber-500"},[o("div",{class:"absolute bottom-10 w-20 -rotate-90 transform whitespace-nowrap"},[o("div",{class:"text-4xl font-bold text-white"}," 1000 French Conjugations ")])],-1),X={class:"flex flex-1 flex-col overflow-y-auto bg-amber-100 p-8"},Y=o("div",{class:"flex rounded-xl bg-amber-500 p-4"},[o("div",{class:"text-center text-xl italic text-white"}," Click a word to the left or right to cycle through the 1000 most popular French verb conjugations! ")],-1),Z={class:"inline-flex flex-col justify-center py-4 text-gray-600"},ee={key:0,class:"mt-2 w-full border border-gray-100 bg-white"},te=["onClick"],oe=o("svg",{class:"absolute left-2 top-2 h-4 w-4",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor"},[o("path",{d:"M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z"})],-1),se={class:"flex p-4"},ae={class:"text-cyan-600 flex-1 text-center text-3xl font-bold"},re={class:"text-amber-500"},ne={class:"grid grid-cols-1 gap-8 md:grid-cols-3 xl:grid-cols-4 xl:gap-12"},le={class:"border-cyan-600 h-full space-y-3 rounded-md border-2 bg-white p-4 shadow shadow-amber-500"},ce={class:"text-2xl font-semibold capitalize text-gray-700"},ie={class:"text-gray-500"},ue={key:1,class:"italic"},xe=R({__name:"index",async setup(h){let l,v;const e=N(0),c=N(""),s=N([]),{data:t}=([l,v]=U(()=>G("/1000_french_conjugations.json",{transform:u=>u},"$lRKQKt9Al2")),l=await l,v(),l),d=C(()=>{if(t.value)return t.value[e.value]}),m=C(()=>{if(t.value!==null)return e.value===0?void 0:t.value[e.value-1]}),w=C(()=>{if(t.value!==null)return e.value+1===t.value.length?void 0:t.value[e.value+1]});V(c,u=>{if(s.value=[],!u)return;let p=0;s.value=t.value.filter(i=>i.word.normalize("NFD").replace(new RegExp("\\p{Diacritic}","gu"),"").includes(u)&&p<=5?(p++,!0):!1)});const j=()=>{t.value&&e.value{e.value>0&&(e.value-=1)},F=u=>{c.value="",s.value=[],e.value=u.word_popularity-1};return(u,p)=>(r(),n("div",P,[o("div",Q,[J,o("div",X,[a(t)&&a(t).length>0&&a(d)?(r(),n(y,{key:0},[Y,o("div",Z,[q(o("input",{"onUpdate:modelValue":p[0]||(p[0]=i=>K(c)?c.value=i:null),class:"rounded-xl border border-2 border-gray-400 p-2 pl-8 focus:border-amber-500 focus:outline-none",type:"search",autocomplete:"off",placeholder:"Search Words"},null,512),[[I,a(c)]]),a(s).length>0?(r(),n("ul",ee,[(r(!0),n(y,null,k(a(s),i=>(r(),n("li",{key:i.word,class:"relative cursor-pointer py-1 pl-8 pr-2 hover:bg-yellow-50 hover:text-gray-900",onClick:g=>F(i)},[oe,B(" "+x(i.word),1)],8,te))),128))])):S("",!0)]),o("div",se,[o("div",{class:"flex-1 cursor-pointer select-none text-center text-2xl text-gray-400",onClick:D},x(a(m)?a(m).word:"-"),1),o("div",ae,[o("span",re," #"+x(a(d).word_popularity),1),B(" "+x(a(d).word),1)]),o("div",{class:"flex-1 cursor-pointer select-none text-center text-2xl text-gray-400",onClick:j},x(a(w)?a(w).word:"-"),1)]),o("div",ne,[(r(!0),n(y,null,k(a(d).conjugations,(i,g)=>(r(),n("div",{key:g},[o("div",le,[o("h1",ce,x(g),1),o("div",ie,[(r(!0),n(y,null,k(i,(L,$)=>(r(),n("p",{key:$},[(r(!0),n(y,null,k(L,(b,A)=>(r(),n("i",{key:A},x(b.text),1))),128))]))),128))])])]))),128))])],64)):(r(),n("div",ue,"Loading..."))])])]))}});export{xe as default}; diff --git a/_nuxt/PIAawFjR.js b/_nuxt/PIAawFjR.js deleted file mode 100644 index d709727c..00000000 --- a/_nuxt/PIAawFjR.js +++ /dev/null @@ -1 +0,0 @@ -import{m as s,c as l,b as t,a8 as a,i as r,f as c,_ as i,o as d}from"./CZZfhpmp.js";const _={},u={class:"container mx-auto my-12 h-screen bg-background font-display lg:my-16"},f={class:"flex flex-col border-2 bg-white"},m={class:"absolute left-2 top-2"};function h(o,e){const n=i;return d(),l("main",null,[t("div",u,[t("div",f,[a(o.$slots,"default")])]),t("div",m,[r(n,{as:"button",to:"/playground",class:"inline-flex items-center rounded px-4 py-2 font-bold text-white hover:text-cyan"},{default:c(()=>e[0]||(e[0]=[t("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor",class:"mr-2 h-6 w-6"},[t("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15M12 9l-3 3m0 0l3 3m-3-3h12.75"})],-1),t("span",null,"Back",-1)])),_:1})])])}const x=s(_,[["render",h]]);export{x as default}; diff --git a/_nuxt/DK7GvCoQ.js b/_nuxt/SY0NXAMn.js similarity index 64% rename from _nuxt/DK7GvCoQ.js rename to _nuxt/SY0NXAMn.js index 2f377d58..e780fa0c 100644 --- a/_nuxt/DK7GvCoQ.js +++ b/_nuxt/SY0NXAMn.js @@ -1 +1 @@ -import{m as o,o as r,c as s,a8 as t}from"./CZZfhpmp.js";const c={};function n(e,a){return r(),s("p",null,[t(e.$slots,"default")])}const f=o(c,[["render",n]]);export{f as default}; +import{m as o,o as r,c as s,a8 as t}from"./K1dcBiIN.js";const c={};function n(e,a){return r(),s("p",null,[t(e.$slots,"default")])}const f=o(c,[["render",n]]);export{f as default}; diff --git a/_nuxt/Dj_Dm3AU.js b/_nuxt/TE8sWSFL.js similarity index 64% rename from _nuxt/Dj_Dm3AU.js rename to _nuxt/TE8sWSFL.js index ffb8b593..47944dd8 100644 --- a/_nuxt/Dj_Dm3AU.js +++ b/_nuxt/TE8sWSFL.js @@ -1 +1 @@ -import{m as o,o as r,c as s,a8 as t}from"./CZZfhpmp.js";const c={};function n(e,a){return r(),s("li",null,[t(e.$slots,"default")])}const f=o(c,[["render",n]]);export{f as default}; +import{m as o,o as r,c as s,a8 as t}from"./K1dcBiIN.js";const c={};function n(e,a){return r(),s("li",null,[t(e.$slots,"default")])}const f=o(c,[["render",n]]);export{f as default}; diff --git a/_nuxt/CZYXMW8W.js b/_nuxt/WSSBFWCz.js similarity index 79% rename from _nuxt/CZYXMW8W.js rename to _nuxt/WSSBFWCz.js index 9e5e569a..3a4ef1a6 100644 --- a/_nuxt/CZYXMW8W.js +++ b/_nuxt/WSSBFWCz.js @@ -1 +1 @@ -import{d as t,a8 as a}from"./CZZfhpmp.js";const o=t({__name:"ProseCode",props:{code:{type:String,default:""},language:{type:String,default:null},filename:{type:String,default:null},highlights:{type:Array,default:()=>[]},meta:{type:String,default:null}},setup(n){return(e,r)=>a(e.$slots,"default")}});export{o as _}; +import{d as t,a8 as a}from"./K1dcBiIN.js";const o=t({__name:"ProseCode",props:{code:{type:String,default:""},language:{type:String,default:null},filename:{type:String,default:null},highlights:{type:Array,default:()=>[]},meta:{type:String,default:null}},setup(n){return(e,r)=>a(e.$slots,"default")}});export{o as _}; diff --git a/_nuxt/Xli_fklN.js b/_nuxt/Xli_fklN.js deleted file mode 100644 index 3a5a3ac1..00000000 --- a/_nuxt/Xli_fklN.js +++ /dev/null @@ -1 +0,0 @@ -import{a as d,v as w,u as y,G as D,H,I as g,d as S,J as _,K as b,L as p}from"./CZZfhpmp.js";import q from"./B1tmNyhF.js";import x from"./DSVbkqRh.js";import"./CuOPeUWs.js";import"./C-v3KzvZ.js";import"./Dnd51l0P.js";import"./B2jTtLqC.js";import"./DvDH6DOc.js";import"./BT7WDeVb.js";import"./CmpoAw97.js";const a=(u,s=y())=>{const e=d(u),m=g();w(()=>d(u),(n=e)=>{if(!s.path||!n)return;const t=Object.assign({},(n==null?void 0:n.head)||{});t.meta=[...t.meta||[]],t.link=[...t.link||[]];const r=t.title||(n==null?void 0:n.title);r&&(t.title=r),m.public.content.host;const c=(t==null?void 0:t.description)||(n==null?void 0:n.description);c&&t.meta.filter(l=>l.name==="description").length===0&&t.meta.push({name:"description",content:c}),t!=null&&t.image||(n==null||n.image),D(()=>H(t))},{immediate:!0})},$=S({name:"ContentDoc",props:{tag:{type:String,required:!1,default:"div"},excerpt:{type:Boolean,default:!1},path:{type:String,required:!1,default:void 0},query:{type:Object,required:!1,default:void 0},head:{type:Boolean,required:!1,default:void 0}},render(u){const{contentHead:s}=g().public.content,e=_(),{tag:m,excerpt:f,path:n,query:t,head:r}=u,c=r===void 0?s:r,l={...t||{},path:n||(t==null?void 0:t.path)||b(y().path),find:"one"},v=(o,i)=>p("pre",null,JSON.stringify({message:"You should use slots with ",slot:o,data:i},null,2));return p(x,l,{default:e!=null&&e.default?({data:o,refresh:i,isPartial:C})=>{var h;return c&&a(o),(h=e.default)==null?void 0:h.call(e,{doc:o,refresh:i,isPartial:C,excerpt:f,...this.$attrs})}:({data:o})=>(c&&a(o),p(q,{value:o,excerpt:f,tag:m,...this.$attrs},{empty:i=>e!=null&&e.empty?e.empty(i):v("default",o)})),empty:o=>{var i;return((i=e==null?void 0:e.empty)==null?void 0:i.call(e,o))||p("p",null,"Document is empty, overwrite this content with #empty slot in .")},"not-found":o=>{var i;return((i=e==null?void 0:e["not-found"])==null?void 0:i.call(e,o))||p("p",null,"Document not found, overwrite this content with #not-found slot in .")}})}}),K=$;export{K as default}; diff --git a/_nuxt/Zyr_YK_I.js b/_nuxt/Zyr_YK_I.js deleted file mode 100644 index 677abc85..00000000 --- a/_nuxt/Zyr_YK_I.js +++ /dev/null @@ -1 +0,0 @@ -import{m as n,o as r,c,b as e,i as s,a8 as d,ab as _}from"./CZZfhpmp.js";const i={},f={class:"pin-b w-full p-4 text-xs font-bold text-white"};function u(t,o){return r(),c("footer",f,o[0]||(o[0]=[e("div",{class:"flex justify-center space-x-2"},[e("a",{class:"hover:cursor-pointer hover:text-blue-200",href:"https://github.com/cmpadden/cmpadden.github.io"}," © Colton Padden"),e("span",null,"•"),e("a",{class:"hover:cursor-pointer hover:text-blue-200",href:"/sitemap.xml"},"Sitemap"),e("span",null,"•"),e("a",{class:"hover:cursor-pointer hover:text-blue-200",href:"/atom"},"RSS")],-1)]))}const p=n(i,[["render",u]]),m={},h={class:"bg-orange-500"},x={class:"rounded-3xl border-[10px] border-orange-500"},b={class:"flex min-h-screen flex-col rounded-3xl bg-background font-display"},v={class:"flex-1"};function g(t,o){const a=_,l=p;return r(),c("div",h,[e("div",x,[e("main",b,[s(a),e("main",v,[d(t.$slots,"default")]),s(l)])])])}const S=n(m,[["render",g]]);export{S as default}; diff --git a/_nuxt/_5NWYBcI.js b/_nuxt/_5NWYBcI.js deleted file mode 100644 index 13bf094b..00000000 --- a/_nuxt/_5NWYBcI.js +++ /dev/null @@ -1 +0,0 @@ -import{m as u,c as v,b as c,o as h}from"./CZZfhpmp.js";const y={data(){return{}},mounted(){document.getElementById("canvas").textContent="";const o=["#FFBA08","#FAA307","#F48C06","#E85D04","#DC2F02","#D00000","#9D0208","#6A040F","#370617","#03071E"],a=e=>{const m=document.getElementById("canvas"),r=m.clientWidth,n=m.clientHeight,f=[{color:o[1],min:0,max:.2,yoff:2},{color:o[2],min:.2,max:.4,yoff:2},{color:o[3],min:.4,max:.6,yoff:2},{color:o[4],min:.6,max:.8,yoff:2},{color:o[5],min:.8,max:1,yoff:2}],l=t=>{e.fill(t.color),e.beginShape();let s=1;for(let i=0;i<=r;i+=10){const x=e.map(e.noise(s,t.yoff),0,1,t.min*n,t.max*n);e.curveVertex(i,x),s+=e.random(.5)}t.yoff+=e.random(-.5,.5),e.curveVertex(r,n),e.curveVertex(0,n),e.endShape(e.CLOSE)},d=()=>{e.clear(),e.background(o[0]),f.forEach(t=>l(t))};e.setup=()=>{e.createCanvas(r,n),e.frameRate(5),e.smooth(),e.stroke(255),e.strokeWeight(3),d(),e.noLoop()},e.mousePressed=()=>{d()}};new this.$p5(a,"canvas")}},p={class:"select-none bg-gradient-to-b from-green-800 to-gray-800"};function g(o,a,e,m,r,n){return h(),v("div",p,a[0]||(a[0]=[c("div",{class:"m-6 grid h-2/3 place-items-center"},[c("div",{class:"font-mono text-white"},[c("div",{id:"canvas",class:"mb-2 h-96 border-2 border-white"}),c("div",{class:"my-2 w-48 text-center md:w-full"}," Click or tap anywhere to redraw the waves! ")])],-1)]))}const E=u(y,[["render",g]]);export{E as default}; diff --git a/_nuxt/builds/latest.json b/_nuxt/builds/latest.json index 3c66922a..e813b36f 100644 --- a/_nuxt/builds/latest.json +++ b/_nuxt/builds/latest.json @@ -1 +1 @@ -{"id":"8ac6cfc2-8695-46be-9b06-7ad33f3a3d43","timestamp":1726174725796} \ No newline at end of file +{"id":"d6ca5b55-ea93-45cf-9a93-ac870132a3e2","timestamp":1727638383859} \ No newline at end of file diff --git a/_nuxt/builds/meta/8ac6cfc2-8695-46be-9b06-7ad33f3a3d43.json b/_nuxt/builds/meta/8ac6cfc2-8695-46be-9b06-7ad33f3a3d43.json deleted file mode 100644 index 21e4331c..00000000 --- a/_nuxt/builds/meta/8ac6cfc2-8695-46be-9b06-7ad33f3a3d43.json +++ /dev/null @@ -1 +0,0 @@ -{"id":"8ac6cfc2-8695-46be-9b06-7ad33f3a3d43","timestamp":1726174725796,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":["/card","/playground/french","/playground","/examples/nested_transitions","/playground/palettes/variance","/playground/chords","/playground/conway","/playground/metronome","/playground/midi","/playground/matrix","/playground/tiling","/playground/palettes/mountains","/playground/plotter","/playground/audio","/playground/waves","/talks","/","/articles","/articles/nuxt-v3-migration","/articles/migrate-truenas-from-core-to-scale","/articles/vim-fugitive-gpg-pinentry","/articles/podcast-transcription-whispercpp","/articles/doctl","/articles/reset-ipmi-password-from-host-os","/articles/quick-tip-rerunning-bash-commands","/articles/nuxt-content-rss-feed","/articles/ssh-ed25519-sk-yubikey","/articles/fennel-initial-exploration","/articles/unit-testing-micropython-with-mocks","/articles/apu2-firmware-upgrade","/articles/docker-selinux-volumes","/articles/persistent-archlinux-usb"]} \ No newline at end of file diff --git a/_nuxt/builds/meta/d6ca5b55-ea93-45cf-9a93-ac870132a3e2.json b/_nuxt/builds/meta/d6ca5b55-ea93-45cf-9a93-ac870132a3e2.json new file mode 100644 index 00000000..d82b93c8 --- /dev/null +++ b/_nuxt/builds/meta/d6ca5b55-ea93-45cf-9a93-ac870132a3e2.json @@ -0,0 +1 @@ +{"id":"d6ca5b55-ea93-45cf-9a93-ac870132a3e2","timestamp":1727638383859,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":["/card","/playground","/playground/french","/playground/palettes/variance","/examples/nested_transitions","/playground/chords","/playground/matrix","/playground/conway","/playground/midi","/playground/metronome","/playground/palettes/mountains","/playground/plotter","/playground/tiling","/playground/audio","/playground/waves","/talks","/","/articles","/articles/migrate-truenas-from-core-to-scale","/articles/nuxt-v3-migration","/articles/vim-fugitive-gpg-pinentry","/articles/podcast-transcription-whispercpp","/articles/nuxt-content-rss-feed","/articles/reset-ipmi-password-from-host-os","/articles/doctl","/articles/quick-tip-rerunning-bash-commands","/articles/fennel-initial-exploration","/articles/ssh-ed25519-sk-yubikey","/articles/unit-testing-micropython-with-mocks","/articles/apu2-firmware-upgrade","/articles/persistent-archlinux-usb","/articles/docker-selinux-volumes"]} \ No newline at end of file diff --git a/_nuxt/g5yxyt4Q.js b/_nuxt/g5yxyt4Q.js new file mode 100644 index 00000000..abaaeae8 --- /dev/null +++ b/_nuxt/g5yxyt4Q.js @@ -0,0 +1 @@ +import{d as C,u as N,w as x,n as R,a as o,o as a,c,b as e,F as g,r as h,e as f,f as _,g as v,t as p,h as b,i as y,_ as B}from"./K1dcBiIN.js";import{_ as T}from"./y2Up_N_N.js";import V from"./mDMTOJLw.js";import{u as $}from"./C6WZwVE2.js";import{q as D}from"./Ce34VGij.js";import"./C-v3KzvZ.js";import"./NnUIAPGH.js";import"./DvDH6DOc.js";const E={key:0,class:"container mx-auto"},q={class:"mb-10 bg-gray-200 p-10 shadow-lg"},A={class:"space-y-6"},F={class:"flex space-x-2"},L=e("div",{class:"text-xs uppercase text-gray-400"},"Category",-1),S={class:"flex flex-col space-y-2 md:flex md:flex-row md:space-x-2 md:space-y-0"},I=e("div",{class:"border-r border-gray-400"},null,-1),M=e("div",{class:"text-xs uppercase text-gray-400"},"Tags",-1),O={class:"flex flex-col space-y-2 md:flex md:flex-row md:space-x-2 md:space-y-0"},j={class:"flex"},z=["src"],G={class:"text-xl font-bold text-gray-700 md:text-3xl"},H={class:"prose max-w-none prose-a:font-bold prose-a:no-underline hover:prose-a:text-orange-500 prose-pre:bg-white prose-pre:text-black"},te=C({__name:"[...slug]",async setup(J){let s,n;const l=N(),{data:t}=([s,n]=x(()=>$("page-data",()=>D(l.path).findOne())),s=await s,n(),s),m={};if(t.value===null||l.path in m){const d=m[l.path]||"/";console.log(d),[s,n]=x(()=>R({path:d})),await s,n()}return(d,K)=>{const u=B,w=T,k=V;return o(t)?(a(),c("div",E,[e("article",q,[e("div",A,[e("div",F,[e("div",null,[L,e("div",S,[(a(!0),c(g,null,h(o(t).categories,(r,i)=>(a(),f(u,{class:"w-min rounded-md bg-background px-2 text-sm font-bold text-white hover:cursor-pointer hover:bg-orange-500",key:i,to:`/articles?category=${r}`},{default:_(()=>[v(p(r),1)]),_:2},1032,["to"]))),128))])]),I,e("div",null,[M,e("div",O,[(a(!0),c(g,null,h(o(t).tags,(r,i)=>(a(),f(u,{class:"w-min rounded-md bg-background px-2 text-sm font-bold text-white hover:cursor-pointer hover:bg-orange-500",key:i,to:`/articles?tag=${r}`},{default:_(()=>[v(p(r),1)]),_:2},1032,["to"]))),128))])])]),e("div",j,[o(t).cover_image?(a(),c("img",{key:0,class:"mr-4 h-16 border-2 border-black",src:o(t).cover_image},null,8,z)):b("",!0),e("h1",G,p(o(t).title),1)])]),e("article",H,[y(k,null,{default:_(()=>[y(w,{value:o(t)},null,8,["value"])]),_:1})])])])):b("",!0)}}});export{te as default}; diff --git a/_nuxt/gYgHqO9f.js b/_nuxt/gYgHqO9f.js deleted file mode 100644 index 53db662d..00000000 --- a/_nuxt/gYgHqO9f.js +++ /dev/null @@ -1 +0,0 @@ -import{d as r,a as n,o as s,c as a,g as e,b as o,h as i}from"./CZZfhpmp.js";const d={key:0},u=r({__name:"ProseScript",props:{src:{type:String,default:""}},setup(c){return(p,t)=>n(!1)?(s(),a("div",d,t[0]||(t[0]=[e(" Rendering the "),o("code",null,"script",-1),e(" element is dangerous and is disabled by default. Consider implementing your own "),o("code",null,"ProseScript",-1),e(" element to have control over script rendering. ")]))):i("",!0)}});export{u as default}; diff --git a/_nuxt/kCftLbeK.js b/_nuxt/kCftLbeK.js deleted file mode 100644 index 9cdf4e65..00000000 --- a/_nuxt/kCftLbeK.js +++ /dev/null @@ -1 +0,0 @@ -import{d as p,I as f,k as u,o as t,c as s,a as i,a8 as n}from"./CZZfhpmp.js";const l=["id"],d=["href"],_=p({__name:"ProseH1",props:{id:{}},setup(r){const c=r,{headings:o}=f().public.mdc,a=u(()=>{var e;return c.id&&(typeof(o==null?void 0:o.anchorLinks)=="boolean"&&(o==null?void 0:o.anchorLinks)===!0||typeof(o==null?void 0:o.anchorLinks)=="object"&&((e=o==null?void 0:o.anchorLinks)==null?void 0:e.h1))});return(e,k)=>(t(),s("h1",{id:e.id},[i(a)?(t(),s("a",{key:0,href:`#${e.id}`},[n(e.$slots,"default")],8,d)):n(e.$slots,"default",{key:1})],8,l))}});export{_ as default}; diff --git a/_nuxt/mDMTOJLw.js b/_nuxt/mDMTOJLw.js new file mode 100644 index 00000000..f1352f7c --- /dev/null +++ b/_nuxt/mDMTOJLw.js @@ -0,0 +1 @@ +import{_ as f}from"./y2Up_N_N.js";import{d as l,v as s,J as d,L as c}from"./K1dcBiIN.js";import"./C-v3KzvZ.js";import"./NnUIAPGH.js";import"./DvDH6DOc.js";const _=l({name:"ContentRenderer",props:{value:{type:Object,required:!1,default:()=>({})},excerpt:{type:Boolean,default:!1},tag:{type:String,default:"div"}},setup(t){s(()=>t.excerpt,n=>{var e,a,i;n&&!((e=t.value)!=null&&e.excerpt)&&(console.warn(`No excerpt found for document content/${(a=t==null?void 0:t.value)==null?void 0:a._path}.${(i=t==null?void 0:t.value)==null?void 0:i._extension}!`),console.warn("Make sure to use in your content if you want to use excerpt feature."))},{immediate:!0})},render(t){var u,o;const n=d(),{value:e,excerpt:a,tag:i}=t,r=a?e==null?void 0:e.excerpt:e==null?void 0:e.body;return!((u=r==null?void 0:r.children)!=null&&u.length)&&(n!=null&&n.empty)?n.empty({value:e,excerpt:a,tag:i,...this.$attrs}):n!=null&&n.default?n.default({value:e,excerpt:a,tag:i,...this.$attrs}):(r==null?void 0:r.type)==="root"&&((o=r==null?void 0:r.children)!=null&&o.length)?c(f,{value:e,excerpt:a,tag:i,...this.$attrs}):c("pre",null,JSON.stringify({message:"You should use slots with ",value:e,excerpt:a,tag:i},null,2))}});export{_ as default}; diff --git a/_nuxt/nVRvli7B.js b/_nuxt/nVRvli7B.js deleted file mode 100644 index 97247e2a..00000000 --- a/_nuxt/nVRvli7B.js +++ /dev/null @@ -1 +0,0 @@ -import s from"./3aFKPIgF.js";import{d as o,J as u,k as f,a0 as m}from"./CZZfhpmp.js";import"./Dnd51l0P.js";const d=o({name:"Markdown",extends:s,setup(t){const{parent:e}=m(),{between:n,default:a}=u(),r=f(()=>typeof t.unwrap=="string"?t.unwrap.split(" "):["*"]);return{fallbackSlot:a,tags:r,between:n,parent:e}}});export{d as default}; diff --git a/_nuxt/wpwljwju.js b/_nuxt/pMxOCLTg.js similarity index 65% rename from _nuxt/wpwljwju.js rename to _nuxt/pMxOCLTg.js index 4a0d63d7..9d478225 100644 --- a/_nuxt/wpwljwju.js +++ b/_nuxt/pMxOCLTg.js @@ -1 +1 @@ -import{m as o,o as n,c as r,a8 as c}from"./CZZfhpmp.js";const s={};function t(e,a){return n(),r("code",null,[c(e.$slots,"default")])}const d=o(s,[["render",t]]);export{d as default}; +import{m as o,o as n,c as r,a8 as c}from"./K1dcBiIN.js";const s={};function t(e,a){return n(),r("code",null,[c(e.$slots,"default")])}const d=o(s,[["render",t]]);export{d as default}; diff --git a/_nuxt/pTPauEmS.js b/_nuxt/pTPauEmS.js new file mode 100644 index 00000000..65341664 --- /dev/null +++ b/_nuxt/pTPauEmS.js @@ -0,0 +1 @@ +import r from"./-GjkDpfn.js";import{d as o,J as u,k as f,a0 as c}from"./K1dcBiIN.js";const i=o({name:"Markdown",extends:r,setup(t){const{parent:e}=c(),{between:n,default:a}=u(),s=f(()=>typeof t.unwrap=="string"?t.unwrap.split(" "):["*"]);return{fallbackSlot:a,tags:s,between:n,parent:e}}});export{i as default}; diff --git a/_nuxt/uYek0qF_.js b/_nuxt/uYek0qF_.js new file mode 100644 index 00000000..7ae71862 --- /dev/null +++ b/_nuxt/uYek0qF_.js @@ -0,0 +1 @@ +import{_ as o}from"./y2Up_N_N.js";import"./K1dcBiIN.js";import"./C-v3KzvZ.js";import"./NnUIAPGH.js";import"./DvDH6DOc.js";export{o as default}; diff --git a/_nuxt/v3tOoUxe.js b/_nuxt/v3tOoUxe.js new file mode 100644 index 00000000..a6290765 --- /dev/null +++ b/_nuxt/v3tOoUxe.js @@ -0,0 +1 @@ +import{a as d,v as w,u as y,G as D,H,I as g,d as S,J as _,K as b,L as u}from"./K1dcBiIN.js";import q from"./mDMTOJLw.js";import x from"./DsRHAFuR.js";import"./y2Up_N_N.js";import"./C-v3KzvZ.js";import"./NnUIAPGH.js";import"./DvDH6DOc.js";import"./C6WZwVE2.js";import"./Ce34VGij.js";const a=(p,s=y())=>{const e=d(p),f=g();w(()=>d(p),(n=e)=>{if(!s.path||!n)return;const t=Object.assign({},(n==null?void 0:n.head)||{});t.meta=[...t.meta||[]],t.link=[...t.link||[]];const r=t.title||(n==null?void 0:n.title);r&&(t.title=r),f.public.content.host;const c=(t==null?void 0:t.description)||(n==null?void 0:n.description);c&&t.meta.filter(l=>l.name==="description").length===0&&t.meta.push({name:"description",content:c}),t!=null&&t.image||(n==null||n.image),D(()=>H(t))},{immediate:!0})},$=S({name:"ContentDoc",props:{tag:{type:String,required:!1,default:"div"},excerpt:{type:Boolean,default:!1},path:{type:String,required:!1,default:void 0},query:{type:Object,required:!1,default:void 0},head:{type:Boolean,required:!1,default:void 0}},render(p){const{contentHead:s}=g().public.content,e=_(),{tag:f,excerpt:m,path:n,query:t,head:r}=p,c=r===void 0?s:r,l={...t||{},path:n||(t==null?void 0:t.path)||b(y().path),find:"one"},v=(o,i)=>u("pre",null,JSON.stringify({message:"You should use slots with ",slot:o,data:i},null,2));return u(x,l,{default:e!=null&&e.default?({data:o,refresh:i,isPartial:C})=>{var h;return c&&a(o),(h=e.default)==null?void 0:h.call(e,{doc:o,refresh:i,isPartial:C,excerpt:m,...this.$attrs})}:({data:o})=>(c&&a(o),u(q,{value:o,excerpt:m,tag:f,...this.$attrs},{empty:i=>e!=null&&e.empty?e.empty(i):v("default",o)})),empty:o=>{var i;return((i=e==null?void 0:e.empty)==null?void 0:i.call(e,o))||u("p",null,"Document is empty, overwrite this content with #empty slot in .")},"not-found":o=>{var i;return((i=e==null?void 0:e["not-found"])==null?void 0:i.call(e,o))||u("p",null,"Document not found, overwrite this content with #not-found slot in .")}})}}),G=$;export{G as default}; diff --git a/_nuxt/PCdpkuPO.js b/_nuxt/v_KFgWUo.js similarity index 64% rename from _nuxt/PCdpkuPO.js rename to _nuxt/v_KFgWUo.js index b09d6731..19088a98 100644 --- a/_nuxt/PCdpkuPO.js +++ b/_nuxt/v_KFgWUo.js @@ -1 +1 @@ -import{m as o,o as r,c as s,a8 as t}from"./CZZfhpmp.js";const c={};function n(e,a){return r(),s("em",null,[t(e.$slots,"default")])}const f=o(c,[["render",n]]);export{f as default}; +import{m as o,o as r,c as s,a8 as t}from"./K1dcBiIN.js";const c={};function n(e,a){return r(),s("em",null,[t(e.$slots,"default")])}const f=o(c,[["render",n]]);export{f as default}; diff --git a/_nuxt/wDya3lie.js b/_nuxt/wDya3lie.js new file mode 100644 index 00000000..2b0d749f --- /dev/null +++ b/_nuxt/wDya3lie.js @@ -0,0 +1 @@ +import{c as e,o as t,b as o}from"./K1dcBiIN.js";const s={class:"flex h-[768px] justify-center border-2 border-gray-500"},r=o("iframe",{src:"https://simple-tempo.com",width:"100%",height:"100%"},null,-1),c=[r],i={__name:"metronome",setup(a){return(n,_)=>(t(),e("main",s,c))}};export{i as default}; diff --git a/_nuxt/y2Up_N_N.js b/_nuxt/y2Up_N_N.js new file mode 100644 index 00000000..55cc1b9d --- /dev/null +++ b/_nuxt/y2Up_N_N.js @@ -0,0 +1 @@ +import{d as j,a0 as ln,a2 as en,k as w,L as z,a3 as on,a4 as P,a5 as tn,a6 as rn,o as an,e as un,a as sn}from"./K1dcBiIN.js";import{p as F,k as cn}from"./C-v3KzvZ.js";import{u as pn}from"./NnUIAPGH.js";class S{constructor(l,o,t){this.property=l,this.normal=o,t&&(this.space=t)}}S.prototype.property={};S.prototype.normal={};S.prototype.space=null;function H(n,l){const o={},t={};let r=-1;for(;++r4&&o.slice(0,4)==="data"&&fn.test(l)){if(l.charAt(4)==="-"){const a=l.slice(5).replace(I,kn);t="data"+a.charAt(0).toUpperCase()+a.slice(1)}else{const a=l.slice(4);if(!I.test(a)){let i=a.replace(yn,bn);i.charAt(0)!=="-"&&(i="-"+i),l="data"+i}}r=T}return new r(t,l)}function bn(n){return"-"+n.toLowerCase()}function kn(n){return n.charAt(1).toUpperCase()}const Cn=H([q,N,X,Y,hn],"html");H([q,N,X,Y,mn],"svg");const A=["a","abbr","address","area","article","aside","audio","b","base","bdi","bdo","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","data","datalist","dd","del","details","dfn","dialog","div","dl","dt","em","embed","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","kbd","label","legend","li","link","main","map","mark","math","menu","menuitem","meta","meter","nav","noscript","object","ol","optgroup","option","output","p","param","picture","pre","progress","q","rb","rp","rt","rtc","ruby","s","samp","script","section","select","slot","small","source","span","strong","style","sub","summary","sup","svg","table","tbody","td","template","textarea","tfoot","th","thead","time","title","tr","track","u","ul","var","video","wbr"],R="default",$=/^@|^v-on:/,Z=/^:|^v-bind:/,J=/^v-model/,Sn=["select","textarea","input"],xn=Object.fromEntries(["p","a","blockquote","code","pre","code","em","h1","h2","h3","h4","h5","h6","hr","img","ul","ol","li","strong","table","thead","tbody","td","th","tr","script"].map(n=>[n,`prose-${n}`])),wn=j({name:"MDCRenderer",props:{body:{type:Object,required:!0},data:{type:Object,default:()=>({})},tag:{type:[String,Boolean],default:void 0},prose:{type:Boolean,default:void 0},components:{type:Object,default:()=>({})}},async setup(n){var i,s,c,g,f,p,y,B;const l=(c=(s=(i=ln())==null?void 0:i.appContext)==null?void 0:s.app)==null?void 0:c.$nuxt,o=(l==null?void 0:l.$route)||(l==null?void 0:l._route),{mdc:t}=((g=l==null?void 0:l.$config)==null?void 0:g.public)||{},r={...(f=t==null?void 0:t.components)!=null&&f.prose&&n.prose!==!1?xn:{},...((p=t==null?void 0:t.components)==null?void 0:p.map)||{},...en(((B=(y=n.data)==null?void 0:y.mdc)==null?void 0:B.components)||{}),...n.components},a=w(()=>{var U;const nn=(((U=n.body)==null?void 0:U.children)||[]).map(x=>x.tag||x.type).filter(x=>!A.includes(x));return Array.from(new Set(nn)).sort().join(".")});return await Un(n.body,{tags:r}),{tags:r,contentKey:a,route:o}},render(n){var f,p,y;const{tags:l,tag:o,body:t,data:r,contentKey:a,route:i}=n;if(!t)return null;const s={...r,tags:l,$route:i},c=o!==!1?E(o||((f=s.component)==null?void 0:f.name)||s.component||"div"):void 0,g=G(t,z,s,s);return c?z(c,{...(p=s.component)==null?void 0:p.props,...this.$attrs,key:a},g):(y=g.default)==null?void 0:y.call(g)}});function Pn(n,l,o,t={}){if(n.type==="text")return l(P,n.value);if(n.type==="comment")return l(tn,null,n.value);const r=n.tag,a=Q(n,o.tags);if(n.tag==="binding")return On(n,l,o,t);const i=E(a);typeof i=="object"&&(i.tag=r);const s=Dn(n,o);return l(i,s,G(n,l,o,{...t,...s}))}function On(n,l,o,t={}){var g,f;const r={...t,$document:o,$doc:o},a=/\.|\[(\d+)\]/,s=((g=n.props)==null?void 0:g.value.trim().split(a).filter(Boolean)).reduce((p,y)=>{if(p&&y in p)return typeof p[y]=="function"?p[y]():p[y]},r),c=(f=n.props)==null?void 0:f.defaultValue;return l(P,s??c??"")}function G(n,l,o,t){const a=(n.children||[]).reduce((s,c)=>{if(!En(c))return s[R].push(c),s;const g=An(c);return s[g]=s[g]||[],c.type==="element"&&s[g].push(...c.children||[]),s},{[R]:[]});return Object.entries(a).reduce((s,[c,g])=>(g.length&&(s[c]=()=>{const f=g.map(p=>Pn(p,l,o,t));return Bn(f)}),s),{})}function Dn(n,l){const{tag:o="",props:t={}}=n;return Object.keys(t).reduce(function(r,a){if(a==="__ignoreMap")return r;const i=t[a];if(J.test(a)&&!Sn.includes(o))return Ln(a,i,r,l);if(a==="v-bind")return Mn(a,i,r,l);if($.test(a))return Rn(a,i,r,l);if(Z.test(a))return Tn(a,i,r,l);const{attribute:s}=vn(Cn,a);return Array.isArray(i)&&i.every(c=>typeof c=="string")?(r[s]=i.join(" "),r):(r[s]=i,r)},{})}function Ln(n,l,o,t){const r=p=>+p,a=p=>p.trim(),i=p=>p,s=n.replace(J,"").split(".").filter(p=>p).reduce((p,y)=>(p[y]=!0,p),{}),c="value",g=s.lazy?"change":"input",f=s.number?r:s.trim?a:i;return o[c]=O(l,t),o.on=o.on||{},o.on[g]=p=>t[l]=f(p),o}function Mn(n,l,o,t){const r=O(l,t);return o=Object.assign(o,r),o}function Rn(n,l,o,t){return n=n.replace($,""),o.on=o.on||{},o.on[n]=()=>O(l,t),o}function Tn(n,l,o,t){return n=n.replace(Z,""),o[n]=O(l,t),o}const E=n=>{if(!A.includes(n)&&!(n!=null&&n.render)&&!(n!=null&&n.ssrRender)){const l=on(F(n),!1);if(typeof l=="object")return l}return n};function O(n,l){const o=n.split(".").reduce((t,r)=>typeof t=="object"?t[r]:void 0,l);return typeof o>"u"?rn(n):o}function An(n){let l="";for(const o of Object.keys(n.props||{}))if(!(!o.startsWith("#")&&!o.startsWith("v-slot:"))){l=o.split(/[:#]/,2)[1];break}return l||R}function En(n){return n.tag==="template"}function Bn(n){const l=[];for(const o of n){const t=l[l.length-1];o.type===P&&(t==null?void 0:t.type)===P?t.children=t.children+o.children:l.push(o)}return l}async function Un(n,l){if(!n)return;const o=Array.from(new Set(t(n,l)));await Promise.all(o.map(async r=>{if(r!=null&&r.render||r!=null&&r.ssrRender||r!=null&&r.__ssrInlineRender)return;const a=E(r);a!=null&&a.__asyncLoader&&!a.__asyncResolved&&await a.__asyncLoader()}));function t(r,a){const i=r.tag;if(r.type==="text"||i==="binding"||r.type==="comment")return[];const s=Q(r,a.tags),c=[];r.type!=="root"&&!A.includes(s)&&c.push(s);for(const g of r.children||[])c.push(...t(g,a));return c}}function Q(n,l){var t;const o=n.tag;return!o||typeof((t=n.props)==null?void 0:t.__ignoreMap)<"u"?o:l[o]||l[F(o)]||l[cn(n.tag)]||o}const zn=wn,Fn=j({__name:"ContentRendererMarkdown",props:{value:{type:Object,required:!0},excerpt:{type:Boolean,default:!1},tag:{type:String,default:"div"},components:{type:Object,default:()=>({})},data:{type:Object,default:()=>({})}},setup(n){const l=n,o=pn().isEnabled(),t=w(()=>{let i=l.value.body||l.value;return l.excerpt&&l.value.excerpt&&(i=l.value.excerpt),i}),r=w(()=>{const{body:i,excerpt:s,...c}=l.value;return{...c,...l.data}}),a=w(()=>({...l.components,...r.value._components||{}}));return(i,s)=>{const c=zn;return an(),un(c,{body:t.value,data:r.value,tag:n.tag,components:a.value,"data-content-id":sn(o)?n.value._id:void 0},null,8,["body","data","tag","components","data-content-id"])}}});export{Fn as _}; diff --git a/_payload.json b/_payload.json index 33734df9..190e3256 100644 --- a/_payload.json +++ b/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["Reactive",2],{},1726174738539] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["Reactive",2],{},1727638396946] \ No newline at end of file diff --git a/api/_content/cache.1726174725311.json b/api/_content/cache.1726174725311.json deleted file mode 100644 index 17c0891b..00000000 --- a/api/_content/cache.1726174725311.json +++ /dev/null @@ -1 +0,0 @@ -{"generatedAt":1726174739055,"generateTime":422,"contents":[{"_path":"/articles/apu2-firmware-upgrade","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Upgrading the Firmware on the PCEngines APU2","description":"I've had a PCEngines APU2 gathering dust for a\nfew years, and have recently decided to dust it off.","date":"2019-12-21","draft":false,"tags":["pcengine","apu"],"categories":["linux"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I've had a "},{"type":"element","tag":"a","props":{"href":"https://pcengines.ch/apu2.htm","rel":["nofollow"]},"children":[{"type":"text","value":"PCEngines APU2"}]},{"type":"text","value":" gathering dust for a\nfew years, and have recently decided to dust it off."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Since the last time the device has been powered on, there have been many great\nimprovements to the firmware, and it was very-much due for an upgrade. The\nfollowing steps outline how the firmware was upgraded on the APU from the\nalready-installed operating system -- CentOS."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I've had a "},{"type":"element","tag":"a","props":{"href":"https://pcengines.ch/apu2.htm","rel":["nofollow"]},"children":[{"type":"text","value":"PCEngines APU2"}]},{"type":"text","value":" gathering dust for a\nfew years, and have recently decided to dust it off."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Since the last time the device has been powered on, there have been many great\nimprovements to the firmware, and it was very-much due for an upgrade. The\nfollowing steps outline how the firmware was upgraded on the APU from the\nalready-installed operating system -- CentOS."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, we will connect to the device over the serial port"}]},{"type":"element","tag":"pre","props":{"code":"screen /dev/tty.usbserial 115200\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"screen /dev/tty.usbserial 115200\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, we will install the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"flashrom"}]},{"type":"text","value":" utility that is needed to update the\nfirmware. Because it is not available in the default "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"yum"}]},{"type":"text","value":" repositories, we\nwill enable the "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Extra Packages for Enterprise Linux"}]},{"type":"text","value":" (EPEL) repository before\ninstallation."}]},{"type":"element","tag":"pre","props":{"code":"sudo yum install epel-release\nsudo yum install flashrom\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" yum"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" epel-release\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" yum"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" flashrom\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Next, we will download the latest version of the firmware that is compatible\nwith the APU2 device from the PC Engines release website:\n"},{"type":"element","tag":"a","props":{"href":"https://pcengines.github.io/","rel":["nofollow"]},"children":[{"type":"text","value":"https://pcengines.github.io/"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"code":"curl -O https://3mdeb.com/open-source-firmware/pcengines/apu2/apu2_v4.11.0.1.rom\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"curl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -O"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" https://3mdeb.com/open-source-firmware/pcengines/apu2/apu2_v4.11.0.1.rom\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And finally, we will flash the firmware..."}]},{"type":"element","tag":"pre","props":{"code":"sudo flashrom -w apu2_v4.11.0.1.rom -p internal:boardmismatch=force\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" flashrom"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -w"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" apu2_v4.11.0.1.rom"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -p"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" internal:boardmismatch=force\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"strong","props":{},"children":[{"type":"text","value":"References:"}]}]},{"type":"element","tag":"ul","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://pcengines.ch/apu2.htm","rel":["nofollow"]},"children":[{"type":"text","value":"https://pcengines.ch/apu2.htm"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://pcengines.github.io/","rel":["nofollow"]},"children":[{"type":"text","value":"https://pcengines.github.io/"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/pcengines/apu2-documentation/blob/master/docs/firmware_flashing.md","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/pcengines/apu2-documentation/blob/master/docs/firmware_flashing.md"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/pcengines/apu2-documentation/blob/master/docs/cold_reset.md","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/pcengines/apu2-documentation/blob/master/docs/cold_reset.md"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/elad/openbsd-apu2","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/elad/openbsd-apu2"}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:apu2-firmware-upgrade.md","_source":"content","_file":"articles/apu2-firmware-upgrade.md","_stem":"articles/apu2-firmware-upgrade","_extension":"md"},{"_path":"/articles/docker-selinux-volumes","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Docker Volume Permissions with SELinux","description":"Unfamiliar with running Docker on a SELinux enabled system, I found myself\nrunning into a bunch of file permission errors while creating volumes.","date":"2019-12-26","draft":false,"tags":["docker","selinux"],"categories":["linux"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Unfamiliar with running Docker on a SELinux enabled system, I found myself\nrunning into a bunch of file permission errors while creating volumes."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Unfamiliar with running Docker on a SELinux enabled system, I found myself\nrunning into a bunch of file permission errors while creating volumes."}]},{"type":"element","tag":"pre","props":{"code":"mkdir: can't create directory '/data': Permission denied\n","language":"txt","meta":"","className":"language-txt shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"mkdir: can't create directory '/data': Permission denied\n"}]}]}]}]},{"type":"element","tag":"hr","props":{},"children":[]},{"type":"element","tag":"pre","props":{"code":"$ docker info --format '{{json .SecurityOptions}}'\n[\n \"name=seccomp,profile=/etc/docker/seccomp.json\",\n \"name=selinux\"\n]\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" docker"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" info"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --format"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" '{{json .SecurityOptions}}'\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"name=seccomp,profile=/etc/docker/seccomp.json\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"name=selinux\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"It turns out that this can be resolved by appending the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":":z"}]},{"type":"text","value":" flag to the volume\nmappings in the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"docker-compose.yml"}]},{"type":"text","value":" file, indicating that the volume content\nis shared."}]},{"type":"element","tag":"pre","props":{"code":"services:\n server:\n volumes:\n - ./data:/data:z\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"services:\n server:\n volumes:\n - ./data:/data:z\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"From the Docker documentation:"}]},{"type":"element","tag":"blockquote","props":{},"children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"z"}]},{"type":"text","value":" option tells Docker that two containers share the volume content. As\na result, Docker labels the content with a shared content label. Shared\nvolume labels allow all containers to read/write content."}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"strong","props":{},"children":[{"type":"text","value":"References"}]}]},{"type":"element","tag":"ul","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.docker.com/engine/reference/commandline/info/","rel":["nofollow"]},"children":[{"type":"text","value":"Docker Docs: Docker Info"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.docker.com/engine/reference/commandline/run/#mount-volumes-from-container---volumes-from","rel":["nofollow"]},"children":[{"type":"text","value":"Docker Docs: Mounting Volumes"}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:docker-selinux-volumes.md","_source":"content","_file":"articles/docker-selinux-volumes.md","_stem":"articles/docker-selinux-volumes","_extension":"md"},{"_path":"/articles/doctl","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Exploring the Digital Ocean `doctl` Utility","description":"I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean doctl command line utility.\nThis proved to be an extremely easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future.","date":"2023-01-01","tags":["linux","digital-ocean"],"categories":["linux"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"doctl"}]},{"type":"text","value":" command line utility.\nThis proved to be an "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"extremely"}]},{"type":"text","value":" easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"doctl"}]},{"type":"text","value":" command line utility.\nThis proved to be an "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"extremely"}]},{"type":"text","value":" easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"To start things off, I had to install and setup authentication to Digital Ocean. Doing\nthis on my Mac machine, I opted to use "},{"type":"element","tag":"a","props":{"href":"https://brew.sh/","rel":["nofollow"]},"children":[{"type":"text","value":"Homebrew"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"# install `doctl`\nbrew install doctl\n\n# setup authentication\ndoctl auth init\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# install `doctl`\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"brew"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" doctl\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# setup authentication\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" auth"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" init\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"While the online "},{"type":"element","tag":"a","props":{"href":"https://docs.digitalocean.com/reference/doctl/reference/compute/droplet/create/","rel":["nofollow"]},"children":[{"type":"text","value":"documentation"}]},{"type":"text","value":" is fantastic, I instead found myself mostly referencing the outputs of "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--help"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute droplet create --help\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" droplet"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" create"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --help\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I had to find the image name of the version of Ubuntu I wanted to install:"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute image list --public | grep ubuntu-22\n\n# 118857366 22.04 (LTS) x64 snapshot Ubuntu ubuntu-22-04-x64 true 7\n# 119383150 22.10 x64 snapshot Ubuntu ubuntu-22-10-x64 true 7\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" image"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --public"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" |"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" grep"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ubuntu-22\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# 118857366 22.04 (LTS) x64 snapshot Ubuntu ubuntu-22-04-x64 true 7\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# 119383150 22.10 x64 snapshot Ubuntu ubuntu-22-10-x64 true 7\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And also the slug of the compute size:"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute size list\n\n# Slug Description Memory VCPUs Disk Price Monthly Price Hourly\n# s-1vcpu-512mb-10gb Basic 512 1 10 4.00 0.005950\n# s-1vcpu-1gb Basic 1024 1 25 6.00 0.008930\n# s-1vcpu-1gb-amd Basic AMD 1024 1 25 7.00 0.010420\n# s-1vcpu-1gb-intel Basic Intel 1024 1 25 7.00 0.010420\n# s-1vcpu-2gb Basic 2048 1 50 12.00 0.017860\n# s-1vcpu-2gb-amd Basic AMD 2048 1 50 14.00 0.020830\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" size"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# Slug Description Memory VCPUs Disk Price Monthly Price Hourly\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-512mb-10gb Basic 512 1 10 4.00 0.005950\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-1gb Basic 1024 1 25 6.00 0.008930\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-1gb-amd Basic AMD 1024 1 25 7.00 0.010420\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-1gb-intel Basic Intel 1024 1 25 7.00 0.010420\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-2gb Basic 2048 1 50 12.00 0.017860\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-2gb-amd Basic AMD 2048 1 50 14.00 0.020830\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I've also configured a few SSH keys with Digital Ocean, and I can have the key (specified by ID) provisioned to the machine using the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--ssh-keys"}]},{"type":"text","value":" flag."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute ssh-key list\n\n# ID Name FingerPrint\n# 1234 mini \n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ssh-key"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# ID Name FingerPrint\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# 1234 mini \n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Also, I wanted to install a few packages to the box upon creation, this can be done easily with the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--user-data-file"}]},{"type":"text","value":" flag to run an initialization script."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"echo 'apt install -y imagemagick zip' > bootstrap.sh\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"echo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 'apt install -y imagemagick zip'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" >"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" bootstrap.sh\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Putting it all together, here is the simple command for creating a small compute instance!"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute droplet create \\\n --image ubuntu-22-10-x64 \\\n --size s-1vcpu-512mb-10gb \\\n --region nyc1 \\\n --ssh-keys 1234 \\\n --user-data-file boostrap.sh \\\n ephemeral\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" droplet"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" create"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --image"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ubuntu-22-10-x64"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --size"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" s-1vcpu-512mb-10gb"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --region"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" nyc1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --ssh-keys"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1234"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --user-data-file"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" boostrap.sh"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ephemeral\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Finally, I can connect, do my thing, and destroy the instance."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute ssh ephemeral\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ssh"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ephemeral\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute droplet delete --force ephemeral\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" droplet"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" delete"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --force"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ephemeral\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"All-in-all, I was up and running in about 20 minutes. What a handy utility!"}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:doctl.md","_source":"content","_file":"articles/doctl.md","_stem":"articles/doctl","_extension":"md"},{"_path":"/articles/fennel-initial-exploration","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Impressions of Fennel with Hammerspoon","description":"A while back I read an introductory book on Lisp programming titled, \"The Little\nSchemer\". This book opened my mind to new (to me) programming paradigms, and left me\nwith a strong desire to find a way to incorporate Lisp programming into my every day\nlife. It took some time, but I believe I've found what I've been looking for: Fennel.","draft":false,"date":"2023-10-22","tags":["lisp","hammerspoon","fennel"],"categories":["lisp"],"cover_image":"/images/dall-e-fennel-hammer.jpeg","excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"A while back I read an introductory book on Lisp programming titled, \"The Little\nSchemer\". This book opened my mind to new (to me) programming paradigms, and left me\nwith a strong desire to find a way to incorporate Lisp programming into my every day\nlife. It took some time, but I believe I've found what I've been looking for: Fennel."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"A while back I read an introductory book on Lisp programming titled, \"The Little\nSchemer\". This book opened my mind to new (to me) programming paradigms, and left me\nwith a strong desire to find a way to incorporate Lisp programming into my every day\nlife. It took some time, but I believe I've found what I've been looking for: Fennel."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The "},{"type":"element","tag":"a","props":{"href":"https://fennel-lang.org/","rel":["nofollow"]},"children":[{"type":"text","value":"Fennel"}]},{"type":"text","value":" programming language is a dialect of Lisp that boasts compatibility with\nLua, and it just so happens that two of my favorite applications are configured with\nexactly that language: "},{"type":"element","tag":"a","props":{"href":"https://www.hammerspoon.org/","rel":["nofollow"]},"children":[{"type":"text","value":"Hammerspoon"}]},{"type":"text","value":", and "},{"type":"element","tag":"a","props":{"href":"https://neovim.io/","rel":["nofollow"]},"children":[{"type":"text","value":"Neovim"}]},{"type":"text","value":"."}]},{"type":"element","tag":"h2","props":{"id":"initial-observations"},"children":[{"type":"text","value":"Initial Observations"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"To initially explore Fennel, I wanted to start small. My Hammerspoon configuration\nconsists of 7 "},{"type":"element","tag":"a","props":{"href":"https://github.com/cmpadden/dotfiles/tree/795749fa17e1310bb001bb7deaa22be8689f0027/hammerspoon/.hammerspoon/modules","rel":["nofollow"]},"children":[{"type":"text","value":"modules"}]},{"type":"text","value":" that I use for operations such as: launching applications,\nmanaging windows, keeping my computer from going to sleep, and general operating system\nautomation. So the plan is to translate these modules into Fennel, while maintaining\nwithout breaking the existing functionality. However, at this point, I wasn't even sure\nhow to embed Fennel into my project..."}]},{"type":"element","tag":"h2","props":{"id":"integrating-fennel-with-hammerspoon"},"children":[{"type":"text","value":"Integrating Fennel with Hammerspoon"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"While official documentation exists describing how to "},{"type":"element","tag":"a","props":{"href":"https://fennel-lang.org/setup#embedding-fennel","rel":["nofollow"]},"children":[{"type":"text","value":"embed fennel"}]},{"type":"text","value":" into your\nproject; it didn't provide me with enough clarity to know my next steps on integrating\nit with Hammerspoon. I found a few resources online demonstrating how to extend the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"package.path"}]},{"type":"text","value":" and "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"package.cpath"}]},{"type":"text","value":" properties in Lua, but I was unable to get this to\nwork."}]},{"type":"element","tag":"ul","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://blog.exupero.org/hammerspoon-with-fennel/","rel":["nofollow"]},"children":[{"type":"text","value":"https://blog.exupero.org/hammerspoon-with-fennel/"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/Hammerspoon/hammerspoon/issues/2377#issuecomment-636331435","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/Hammerspoon/hammerspoon/issues/2377#issuecomment-636331435"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/agzam/spacehammer/blob/master/init.lua","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/agzam/spacehammer/blob/master/init.lua"}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Ultimately, I opted to include the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"fennel.lua"}]},{"type":"text","value":" file to my Hammerspoon configuration,\nand while not ideal, it does make the configuration nicely self-contained. I'll leave it\nas a future task to include the module installed with LuaRocks."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"With Fennel now included in my Hammerspoon configuration, all I need to do is configure\nthe "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"fennel.path"}]},{"type":"text","value":" to point to the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"*.fnl"}]},{"type":"text","value":" files in the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":".hammerspoon/"}]},{"type":"text","value":" directory, and\nttranslating these modules can begin!"}]},{"type":"element","tag":"pre","props":{"className":"language-lua shiki shiki-themes github-light","code":"-- init.lua\n\nlocal fennel = require('fennel')\n\nfennel.path = package.path .. \";\" .. os.getenv(\"HOME\") .. \"/.hammerspoon/?.fnl\"\n\ntable.insert(package.loaders or package.searchers, fennel.searcher)\n\nrequire 'main'\n","language":"lua","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"-- init.lua\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"local"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" fennel "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" require"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'fennel'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"fennel."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"path"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" package.path"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" .."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \";\" "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":".."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" os.getenv"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"HOME\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":".."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"/.hammerspoon/?.fnl\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"table.insert"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"package.loaders"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" or"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" package.searchers"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", fennel."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"searcher"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"require"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 'main'\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"translating-lua-to-fennel"},"children":[{"type":"text","value":"Translating Lua to Fennel"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"As a Fennel novice, I was happy to see that the Fennel project provides an online\ncross-compiler for Lua and Fennel called "},{"type":"element","tag":"a","props":{"href":"https://fennel-lang.org/see","rel":["nofollow"]},"children":[{"type":"text","value":"anti-fennel"}]},{"type":"text","value":", and while it can generate some\nstrange-looking Fennel code, it was an extremely useful tool for me to get\nup-and-running right away. For example, by pasting the simple "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sleep"}]},{"type":"text","value":" function\nfrom the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"helpers"}]},{"type":"text","value":" module into the compiler:"}]},{"type":"element","tag":"pre","props":{"className":"language-lua shiki shiki-themes github-light","code":"function sleep(ms)\n os.execute(\"sleep \" .. tonumber(ms) / 1000)\nend\n","language":"lua","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"function"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" sleep"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(ms)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" os.execute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"sleep \" "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":".."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" tonumber"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(ms) "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"/"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1000"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"end\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"className":"language-lisp shiki shiki-themes github-light","code":"(fn sleep [ms]\n (os.execute (.. \"sleep \" (/ (tonumber ms) 1000))))\n","language":"lisp","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(fn "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"sleep"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" [ms]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (os.execute (.. "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"sleep \""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"/"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (tonumber ms) "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"1000"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"))))\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"As another example, here is the output for my "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"caffeine"}]},{"type":"text","value":" toggle:"}]},{"type":"element","tag":"pre","props":{"className":"language-lua shiki shiki-themes github-light","code":"hs.hotkey.bind(HYPER, \"0\", function()\n hs.caffeinate.toggle(\"displayIdle\")\n if hs.caffeinate.get(\"displayIdle\") then\n helpers:show(\"Caffeine Enabled\", nil, helpers.styles.success, helpers.assets.check)\n else\n helpers:show(\"Caffeine Disabled\", nil, helpers.styles.error, helpers.assets.ban)\n end\nend)\n","language":"lua","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"hs."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"hotkey"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"bind"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(HYPER, "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"0\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"function"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"()\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" hs."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"caffeinate"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"toggle"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"displayIdle\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" if"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" hs."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"caffeinate"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"get"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"displayIdle\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"then\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" helpers"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":":"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"show"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Caffeine Enabled\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"nil"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", helpers."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"styles"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"success"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", helpers."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"assets"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"check"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" else\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" helpers"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":":"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"show"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Caffeine Disabled\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"nil"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", helpers."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"styles"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"error"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", helpers."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"assets"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"ban"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" end\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"end"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"className":"language-lisp shiki shiki-themes github-light","code":"(hs.hotkey.bind HYPER :0\n (fn [] (hs.caffeinate.toggle :displayIdle)\n (if (hs.caffeinate.get :displayIdle)\n (helpers:show \"Caffeine Enabled\" nil helpers.styles.success helpers.assets.check)\n (helpers:show \"Caffeine Disabled\" nil helpers.styles.error helpers.assets.ban)))) \n","language":"lisp","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(hs.hotkey.bind HYPER "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":":0\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (fn [] (hs.caffeinate.toggle "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":":displayIdle"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"if"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (hs.caffeinate.get "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":":displayIdle"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"helpers"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":":show "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Caffeine Enabled\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" nil"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" helpers.styles.success helpers.assets.check)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"helpers"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":":show "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Caffeine Disabled\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" nil"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" helpers.styles.error helpers.assets.ban))))\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This was especially helpful for more gnarly modules like the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"window"}]},{"type":"text","value":" module used for\nwindow management, and seeing the Lua and Fennel code side-by-side was a kick starter in\nlearning the language!"}]},{"type":"element","tag":"h2","props":{"id":"next-steps"},"children":[{"type":"text","value":"Next Steps"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"While my Fennel Hammerspoon configuration now works with parity to its Lua counterpart,\nI have not yet added new features or modules. I look forward to writing new Fennel code,\nand deepen my understanding of Lisp and the Fennel programming language."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Additionally, before beginning this endeavor, I was already aware of projects like\n"},{"type":"element","tag":"a","props":{"href":"https://github.com/agzam/spacehammer","rel":["nofollow"]},"children":[{"type":"text","value":"spacehammer"}]},{"type":"text","value":"; a wildly impressive Hammerspoon configuration written in Fennel, but,\nI wanted to start small and learn the integration myself. However, with the basics out\nof the way, I hope to explore this project further, and seek lessons-learned for the\nconfiguration of my own."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The full pull-request for translating my Lua Hammerspoon configuration to Fennel can be\nfound here: "},{"type":"element","tag":"a","props":{"href":"https://github.com/cmpadden/dotfiles/pull/19/files","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/cmpadden/dotfiles/pull/19/files"}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"initial-observations","depth":2,"text":"Initial Observations"},{"id":"integrating-fennel-with-hammerspoon","depth":2,"text":"Integrating Fennel with Hammerspoon"},{"id":"translating-lua-to-fennel","depth":2,"text":"Translating Lua to Fennel"},{"id":"next-steps","depth":2,"text":"Next Steps"}]}},"_type":"markdown","_id":"content:articles:fennel-initial-exploration.md","_source":"content","_file":"articles/fennel-initial-exploration.md","_stem":"articles/fennel-initial-exploration","_extension":"md"},{"_path":"/articles/migrate-truenas-from-core-to-scale","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Migrate to TrueNAS Scale from TrueNAS Core","description":"TrueNAS Scale offers a variety of interesting features that are not supported in its TrueNAS Core counterpart. Most notably, because the base operating system is Debian Linux, opposed to FreeBSD, there is native support for Linux containers via Docker, and Kubernetes Pods! This post walks through the steps required to upgrade from TrueNAS Core to TrueNAS Scale.","date":"2021-12-28","tags":["homelab","supermicro","truenas"],"categories":["homelab"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"TrueNAS Scale offers a variety of interesting features that are not supported in its TrueNAS Core counterpart. Most notably, because the base operating system is Debian Linux, opposed to FreeBSD, there is native support for Linux containers via Docker, and Kubernetes Pods! This post walks through the steps required to upgrade from TrueNAS Core to TrueNAS Scale."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"TrueNAS Scale offers a variety of interesting features that are not supported in its TrueNAS Core counterpart. Most notably, because the base operating system is Debian Linux, opposed to FreeBSD, there is native support for Linux containers via Docker, and Kubernetes Pods! This post walks through the steps required to upgrade from TrueNAS Core to TrueNAS Scale."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Thankfully, the upgrade procedure to migrate from TrueNAS Core to TrueNAS Scale is relatively straight forward. All it requires is to create a bootable USB of the TrueNAS Scale image, boot the USB, and select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Install/Upgrade"}]},{"type":"text","value":" in the installation wizard. But for the sake of being thorough, you can find instructions on how to backup system configurations and install the OS below."}]},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Make a backup of your system’s configuration\n"},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Navigate to "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"System > General"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Click "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Save Config"}]},{"type":"text","value":", check the "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Export Secret Seed"}]},{"type":"text","value":" box, and click "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Save"}]}]}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Export dataset keys for the encrypted pools\n"},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Navigate to "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Storage > Pools"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Click the cog icon, and select "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Export Dataset Keys"}]}]}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Insert the TrueNAS Core bootable USB into the NAS"}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"From the Supermicro IPMI interface select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Remote Control"}]},{"type":"text","value":" and "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"iKVM/HTML5"}]},{"type":"text","value":" and select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Reboot"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Select the bootable USB as the boot device"}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"From the TrueNAS installation wizard, select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Install/Upgrade"}]},{"type":"text","value":", select the drive that contains the TrueNAS installation, and select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Upgrade Install"}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Reboot the device, and voila — you should be up-and-running! Give the system a quick rundown to validate that your settings and pools have transferred correctly, and then enjoy all the container goodness!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"For a breakdown of the differences between TrueNAS Core, Enterprise, and Scale, you can reference "},{"type":"element","tag":"a","props":{"href":"https://www.truenas.com/help-me-choose/","rel":["nofollow"]},"children":[{"type":"text","value":"this table"}]},{"type":"text","value":"."}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:migrate-truenas-from-core-to-scale.md","_source":"content","_file":"articles/migrate-truenas-from-core-to-scale.md","_stem":"articles/migrate-truenas-from-core-to-scale","_extension":"md"},{"_path":"/articles/nuxt-content-rss-feed","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"How To Add an RSS Feed to a Nuxt Website","description":"If you are a user of Nuxt Content and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application.","draft":false,"date":"2024-01-06","tags":["nuxt","rss"],"categories":["programming"],"cover_image":"/images/nuxt-content-rss-feed.jpg","excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you are a user of "},{"type":"element","tag":"a","props":{"href":"https://content.nuxt.com/","rel":["nofollow"]},"children":[{"type":"text","value":"Nuxt Content"}]},{"type":"text","value":" and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you are a user of "},{"type":"element","tag":"a","props":{"href":"https://content.nuxt.com/","rel":["nofollow"]},"children":[{"type":"text","value":"Nuxt Content"}]},{"type":"text","value":" and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application."}]},{"type":"element","tag":"h2","props":{"id":"preface"},"children":[{"type":"text","value":"Preface"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In version 2 of Nuxt, the community module, "},{"type":"element","tag":"a","props":{"href":"https://github.com/nuxt-community/feed-module","rel":["nofollow"]},"children":[{"type":"text","value":"nuxt-community/feed-module"}]},{"type":"text","value":" was a popular choice for adding an RSS feed to your website. However, there has been an unresolved "},{"type":"element","tag":"a","props":{"href":"https://github.com/nuxt-community/feed-module/issues/106","rel":["nofollow"]},"children":[{"type":"text","value":"open issue"}]},{"type":"text","value":" since April 1st, 2022 to add support for Nuxt v3. Thankfully, implementing this feature without a module is relatively straight forward."}]},{"type":"element","tag":"h2","props":{"id":"instructions"},"children":[{"type":"text","value":"Instructions"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, install the "},{"type":"element","tag":"a","props":{"href":"https://www.npmjs.com/package/feed","rel":["nofollow"]},"children":[{"type":"text","value":"feed"}]},{"type":"text","value":" library into your project:"}]},{"type":"element","tag":"pre","props":{"className":"language-shell shiki shiki-themes github-light","code":"npm i -D feed\n","language":"shell","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"npm"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" i"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -D"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" feed\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, create a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"server/"}]},{"type":"text","value":" folder in your project if it does not already exist, and create a file named "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"server/routes/atom.ts"}]},{"type":"text","value":"."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Here, we will leverage the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"feed"}]},{"type":"text","value":" library and construct an XML representation of our Nuxt content. As you can see, we first define our "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"feed"}]},{"type":"text","value":" with metadata associated with our RSS feed. This will be used by RSS readers to provide context to the end user. Then, we query our Nuxt content with "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"serverQueryContent"}]},{"type":"text","value":" and append a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"feed.addItem"}]},{"type":"text","value":" for each article."}]},{"type":"element","tag":"pre","props":{"className":"language-ts shiki shiki-themes github-light","code":"import { serverQueryContent } from '#content/server';\nimport { Feed } from 'feed';\n\nconst BASE_URL = \"https://mywebsite.com\"\nconst AUTHOR_NAME = \"Firstname Lastname\"\n\nexport default defineEventHandler(async (event) => {\n\n const feed = new Feed({\n title: \"My Title\",\n description: \"My Description\",\n id: BASE_URL,\n link: BASE_URL,\n language: \"en\",\n image: `${BASE_URL}/images/placeholder.png`,\n favicon: `${BASE_URL}/favicon.ico`,\n copyright: `All rights reserved ${new Date().getFullYear()}, ${AUTHOR_NAME}`,\n updated: new Date(),\n generator: \"Nuxt static site generation + Feed for Node.js\",\n feedLinks: {\n atom: `${BASE_URL}/atom`\n },\n author: {\n name: AUTHOR_NAME,\n }\n });\n\n const articles = await serverQueryContent(event).find();\n\n articles.forEach((article) => {\n feed.addItem({\n title: article.title ? article.title : \"Missing Title\",\n id: article._path,\n link: `${BASE_URL}${article._path}`,\n description: article.description,\n author: [\n {\n name: AUTHOR_NAME,\n },\n ],\n date: new Date(article.date),\n image: article.cover_image ? `${BASE_URL}/${article.cover_image}` : undefined\n });\n });\n\n return feed.atom1();\n});\n","language":"ts","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" { serverQueryContent } "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" '#content/server'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":";\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" { Feed } "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 'feed'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":";\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"https://mywebsite.com\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" AUTHOR_NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"Firstname Lastname\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"export"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" default"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" defineEventHandler"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"async"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"event"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"=>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" feed"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" Feed"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" title: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"My Title\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" description: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"My Description\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":12},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" id: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":13},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" link: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":14},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" language: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"en\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":15},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" image: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}/images/placeholder.png`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":16},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" favicon: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}/favicon.ico`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":17},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" copyright: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`All rights reserved ${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" Date"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"()."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"getFullYear"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"()"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}, ${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"AUTHOR_NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":18},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" updated: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" Date"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(),\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":19},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" generator: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Nuxt static site generation + Feed for Node.js\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":20},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" feedLinks: {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":21},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" atom: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}/atom`\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":22},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" },\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":23},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" author: {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":24},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" name: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"AUTHOR_NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":25},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" }\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":26},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":27},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":28},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" articles"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" await"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" serverQueryContent"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(event)."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"find"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"();\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":29},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":30},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" articles."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"forEach"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"article"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"=>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":31},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" feed."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"addItem"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":32},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" title: article.title "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"?"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" article.title "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":":"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"Missing Title\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":33},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" id: article._path,\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":34},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" link: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"article"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"_path"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":35},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" description: article.description,\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":36},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" author: [\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":37},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":38},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" name: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"AUTHOR_NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":39},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" },\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":40},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ],\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":41},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" date: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" Date"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(article.date),\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":42},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" image: article.cover_image "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"?"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" `${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}/${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"article"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"cover_image"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" :"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" undefined\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":43},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":44},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":45},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":46},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" return"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" feed."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"atom1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"();\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":47},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"});\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And that's just about it! Except, if you are statically generating your website with the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"nuxt generate"}]},{"type":"text","value":" command, you will need to configure this server-side route to be pre-rendered on site generation. This is as simple as adding a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"nitro"}]},{"type":"text","value":" "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"prerender"}]},{"type":"text","value":" definition in your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"nuxt.config.ts"}]},{"type":"text","value":" file, like so:"}]},{"type":"element","tag":"pre","props":{"className":"language-ts shiki shiki-themes github-light","code":"nitro: {\n prerender: {\n routes: ['/atom']\n }\n}\n","language":"ts","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"nitro"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" prerender"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" routes"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": ["}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/atom'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" }\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"}\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"bonus"},"children":[{"type":"text","value":"Bonus"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"You may also be interested in adding a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sitemap.xml"}]},{"type":"text","value":" to your website. This can be done in almost an identical fashion!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Install the dependency:"}]},{"type":"element","tag":"pre","props":{"className":"language-shell shiki shiki-themes github-light","code":"npm i -D sitemap\n","language":"shell","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"npm"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" i"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -D"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" sitemap\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Create a route at "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"server/routes/sitemap.xml.ts"}]},{"type":"text","value":":"}]},{"type":"element","tag":"pre","props":{"className":"language-ts shiki shiki-themes github-light","code":"import { serverQueryContent } from '#content/server';\nimport { SitemapStream, streamToPromise } from 'sitemap';\n\nexport default defineEventHandler(async (event) => {\n const articles = await serverQueryContent(event).find();\n\n const sitemap = new SitemapStream({ hostname: 'https://my-website.com/' });\n\n // Add non nuxt content endpoints here\n sitemap.write({ url: '/' });\n sitemap.write({ url: '/articles' });\n\n // Dynamically generate routes for Nuxt markdown content\n articles.forEach((article) => sitemap.write({ url: article._path, changefreq: 'monthly' }));\n sitemap.end();\n\n return (await streamToPromise(sitemap));\n});\n","language":"ts","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" { serverQueryContent } "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" '#content/server'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":";\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" { SitemapStream, streamToPromise } "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 'sitemap'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":";\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"export"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" default"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" defineEventHandler"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"async"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"event"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"=>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" articles"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" await"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" serverQueryContent"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(event)."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"find"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"();\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" sitemap"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" SitemapStream"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({ hostname: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'https://my-website.com/'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":" // Add non nuxt content endpoints here\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" sitemap."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"write"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({ url: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" sitemap."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"write"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({ url: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/articles'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":12},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":13},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":" // Dynamically generate routes for Nuxt markdown content\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":14},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" articles."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"forEach"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"article"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"=>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" sitemap."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"write"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({ url: article._path, changefreq: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'monthly'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" }));\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":15},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" sitemap."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"end"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"();\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":16},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":17},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" return"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"await"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" streamToPromise"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(sitemap));\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":18},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"});\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And add the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"prerender"}]},{"type":"text","value":" entry in your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"nuxt.config.ts"}]},{"type":"text","value":":"}]},{"type":"element","tag":"pre","props":{"className":"language-ts shiki shiki-themes github-light","code":"nitro: {\n prerender: {\n routes: ['/sitemap.xml', '/atom']\n }\n}\n","language":"ts","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"nitro"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" prerender"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" routes"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": ["}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/sitemap.xml'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/atom'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" }\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"}\n"}]}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"preface","depth":2,"text":"Preface"},{"id":"instructions","depth":2,"text":"Instructions"},{"id":"bonus","depth":2,"text":"Bonus"}]}},"_type":"markdown","_id":"content:articles:nuxt-content-rss-feed.md","_source":"content","_file":"articles/nuxt-content-rss-feed.md","_stem":"articles/nuxt-content-rss-feed","_extension":"md"},{"_path":"/articles/nuxt-v3-migration","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"This Website Has Been Migrated to Nuxt 3 🎉","description":"This website has been migrated to the latest version of the Nuxt web framework, and with it comes all of the exciting goodies that the Vue and Nuxt teams have been concocting over the past few years.\nNot to mention, all of the great plugins in the Vue ecosystem!","date":"2022-12-31","tags":["nuxt"],"categories":["web"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This website has been migrated to the latest version of the Nuxt web framework, and with it comes all of the exciting goodies that the Vue and Nuxt teams have been concocting over the past few years.\nNot to mention, all of the great plugins in the Vue ecosystem!"}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This website has been migrated to the latest version of the Nuxt web framework, and with it comes all of the exciting goodies that the Vue and Nuxt teams have been concocting over the past few years.\nNot to mention, all of the great plugins in the Vue ecosystem!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you're curious what changes were required to make the migration, you can check out "},{"type":"element","tag":"a","props":{"href":"https://github.com/cmpadden/cmpadden.github.io/pull/3","rel":["nofollow"]},"children":[{"type":"text","value":"pull request #3"}]},{"type":"text","value":" in the GitHub repository."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"img","props":{"alt":"Screenshot of Nuxt Migration Pull Request","src":"/images/nuxt-migration-pr.png"},"children":[]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"While the documentation for making this migration is great, there were many breaking changes, and the overall process was quite tedious.\nFor this reason, I opted to generate a new project entirely, and port existing code to this clean slate.\nI believe that this resulted in a project with a bit less cruft."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The most valuable resources for making these changes include:"}]},{"type":"element","tag":"ul","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://nuxt.com/docs/migration/overview","rel":["nofollow"]},"children":[{"type":"text","value":"The Nuxt Migration Guide"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://nuxt.com/docs/getting-started/introduction","rel":["nofollow"]},"children":[{"type":"text","value":"The Nuxt Framework Guide"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://tailwindcss.nuxt.dev/","rel":["nofollow"]},"children":[{"type":"text","value":"Nuxt Tailwind Module Documentation"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://content.nuxtjs.org/","rel":["nofollow"]},"children":[{"type":"text","value":"Nuxt Content Module Documentation"}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Part of the delay for doing this upgrade was in waiting for module developers to support this major release.\nI'm super thankful for all of the hard work they've don, and I'm excited to explore all of the new features available!\nI just hope that the breaking changes in this release don't cause too much fracturing of the community, as it does feel like déjà vu of Python 2 and 3."}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:nuxt-v3-migration.md","_source":"content","_file":"articles/nuxt-v3-migration.md","_stem":"articles/nuxt-v3-migration","_extension":"md"},{"_path":"/articles/persistent-archlinux-usb","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Create a Persistent Arch Linux Bootable USB with Vagrant","description":"When installing a linux distribution, it is common for the instructions to have\nthe user create a bootable USB, boot from the device, and proceed with the\ninstallation procedure from that live medium. However, this blog post will\noutline an alternative approach where a virtual machine created with Vagrant\nwill be used in favor of the live medium.","date":"2020-01-09","draft":false,"tags":["vagrant","archlinux"],"categories":["linux"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"When installing a linux distribution, it is common for the instructions to have\nthe user create a bootable USB, boot from the device, and proceed with the\ninstallation procedure from that live medium. However, this blog post will\noutline an alternative approach where a virtual machine created with Vagrant\nwill be used in favor of the live medium."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"When installing a linux distribution, it is common for the instructions to have\nthe user create a bootable USB, boot from the device, and proceed with the\ninstallation procedure from that live medium. However, this blog post will\noutline an alternative approach where a virtual machine created with Vagrant\nwill be used in favor of the live medium."}]},{"type":"element","tag":"h1","props":{"id":"preface"},"children":[{"type":"text","value":"Preface"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The original intention was to use Docker for this process -- leveraging the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--device"}]},{"type":"text","value":" flag and mounting the target USB device in the Docker container,\nbut the underlying hypervisor in Docker Desktop for Mac does not support this.\n"},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.docker.com/docker-for-mac/docker-toolbox/","rel":["nofollow"]},"children":[{"type":"text","value":"1"}]},{"type":"text","value":" "},{"type":"element","tag":"a","props":{"href":"https://github.com/moby/hyperkit","rel":["nofollow"]},"children":[{"type":"text","value":"2"}]},{"type":"text","value":" "},{"type":"element","tag":"a","props":{"href":"https://github.com/docker/for-mac/issues/900","rel":["nofollow"]},"children":[{"type":"text","value":"3"}]}]},{"type":"text","value":" While there are workarounds using Docker\nMachine, Vagrant felt like the path of least resistance."}]},{"type":"element","tag":"h1","props":{"id":"instructions"},"children":[{"type":"text","value":"Instructions"}]},{"type":"element","tag":"h2","props":{"id":"create-an-arch-linux-virtual-machine-with-vagrant"},"children":[{"type":"text","value":"Create an Arch Linux Virtual Machine with Vagrant"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Get the latest Arch Linux image "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://app.vagrantup.com/archlinux/boxes/archlinux","rel":["nofollow"]},"children":[{"type":"text","value":"4"}]}]},{"type":"text","value":" from the Vagrant Cloud Box\nCatalog."}]},{"type":"element","tag":"pre","props":{"code":"vagrant box add archlinux/archlinux\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"vagrant"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" box"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" add"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" archlinux/archlinux\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Determine the USB vendor information for the thumb-drive that we will\npass-through to the virtual machine. Using the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"VBoxManage"}]},{"type":"text","value":" utility that comes\nwith Virtual Box, list the devices, and make note of the Vendor and Product ID."}]},{"type":"element","tag":"pre","props":{"code":" VBoxManage list usbhost\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" VBoxManage"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" usbhost\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Create a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Vagrantfile"}]},{"type":"text","value":" with "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"archlinx/archlinux"}]},{"type":"text","value":" as the target box, and the USB\ndevice information that is passed through. "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://antonyjepson.wordpress.com/2012/01/26/quickly-attaching-usb-devices-to-virtualbox-guests-using-vboxmanage/","rel":["nofollow"]},"children":[{"type":"text","value":"5"}]},{"type":"text","value":" "},{"type":"element","tag":"a","props":{"href":"https://gist.github.com/dscape/7d829c0c116ef419f963","rel":["nofollow"]},"children":[{"type":"text","value":"6"}]}]},{"type":"text","value":" Vagrant\noffers a handy customization parameter "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"vb.customize"}]},{"type":"text","value":" that calls the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"VBoxManage"}]},{"type":"text","value":" command under-the-hood, allowing one to enable the guest machine\nto access the host machine's USB devices."}]},{"type":"element","tag":"pre","props":{"code":"# -*- mode: ruby -*-\n# vi: set ft=ruby :\n\nVagrant.configure(\"2\") do |config|\n config.vm.box = \"archlinux/archlinux\"\n config.vm.provider \"virtualbox\" do |vb|\n vb.name = \"archlinux\"\n vb.customize ['modifyvm', :id, '--usb', 'on']\n vb.customize ['usbfilter', 'add', '1', '--target', :id, '--name', 'SanDisk Ultra Fit', '--vendorid', '0x0781', '--productid', '0x5583']\n end\nend\n","language":"txt","meta":"","className":"language-txt shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"# -*- mode: ruby -*-\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"# vi: set ft=ruby :\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Vagrant.configure(\"2\") do |config|\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" config.vm.box = \"archlinux/archlinux\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" config.vm.provider \"virtualbox\" do |vb|\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" vb.name = \"archlinux\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" vb.customize ['modifyvm', :id, '--usb', 'on']\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" vb.customize ['usbfilter', 'add', '1', '--target', :id, '--name', 'SanDisk Ultra Fit', '--vendorid', '0x0781', '--productid', '0x5583']\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" end\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"end\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"When virtual machine is brought up, the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"usbfilter"}]},{"type":"text","value":" is applied, and the guest\nis able to access to the host machine's USB device that was specified in the\nfilter."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Start the machine, "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ssh"}]},{"type":"text","value":" into the guest, and list the devices to confirm that\nthe USB device is available (see: "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"/dev/sdb"}]},{"type":"text","value":")."}]},{"type":"element","tag":"pre","props":{"code":"$ vagrant up\n$ vagrant ssh\n[vagrant@archlinux ~]$ lsblk\nNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT\nsda 8:0 0 20G 0 disk\n├─sda1 8:1 0 1.9G 0 part [SWAP]\n└─sda2 8:2 0 18.1G 0 part /\nsdb 8:16 1 28.7G 0 disk\n└─sdb1 8:17 1 8G 0 part\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" vagrant"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" up\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" vagrant"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ssh\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[vagrant@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]$ lsblk\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" MAJ:MIN"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" RM"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" SIZE"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" RO"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" TYPE"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" MOUNTPOINT\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sda"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 20G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" disk\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"├─sda1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 1.9G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" part"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" [SWAP]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"└─sda2"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:2"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 18.1G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" part"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" /\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sdb"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:16"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 28.7G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" disk\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"└─sdb1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:17"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" part\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"install-arch-linux-on-the-usb-drive"},"children":[{"type":"text","value":"Install Arch Linux on the USB Drive"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The "},{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/Installation_guide","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Installation Guide"}]},{"type":"text","value":" outlines the installation procedure in\ngreat detail -- the following steps follow this closely with a few alteration\ndue to installing onto removable media."}]},{"type":"element","tag":"h3","props":{"id":"partition-the-disk-uefi-with-gpt"},"children":[{"type":"text","value":"Partition the Disk (UEFI with GPT)"}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# fdisk /dev/sdb\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# fdisk /dev/sdb\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"code":"Command (m for help): p\nDisk /dev/sdb: 28.66 GiB, 30752636928 bytes, 60063744 sectors\nDisk model: Ultra Fit\nUnits: sectors of 1 * 512 = 512 bytes\nSector size (logical/physical): 512 bytes / 512 bytes\nI/O size (minimum/optimal): 512 bytes / 512 bytes\nDisklabel type: gpt\nDisk identifier: E1D6C445-1B79-AB4D-A442-FA4AD6DF4ECC\n\nDevice Start End Sectors Size Type\n/dev/sdb1 2048 1050623 1048576 512M EFI System\n/dev/sdb2 1050624 60063710 59013087 28.1G Linux filesystem\n\nFilesystem/RAID signature on partition 1 will be wiped.\n","language":"txt","meta":"","className":"language-txt shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Command (m for help): p\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Disk /dev/sdb: 28.66 GiB, 30752636928 bytes, 60063744 sectors\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Disk model: Ultra Fit\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Units: sectors of 1 * 512 = 512 bytes\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Sector size (logical/physical): 512 bytes / 512 bytes\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"I/O size (minimum/optimal): 512 bytes / 512 bytes\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Disklabel type: gpt\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Disk identifier: E1D6C445-1B79-AB4D-A442-FA4AD6DF4ECC\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Device Start End Sectors Size Type\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"/dev/sdb1 2048 1050623 1048576 512M EFI System\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":12},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"/dev/sdb2 1050624 60063710 59013087 28.1G Linux filesystem\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":13},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":14},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Filesystem/RAID signature on partition 1 will be wiped.\n"}]}]}]}]},{"type":"element","tag":"h3","props":{"id":"format-the-partitions"},"children":[{"type":"text","value":"Format the Partitions"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The UEFI specification mandates support for FAT file-systems, and FAT32 is\nrecommended for removable media. "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/EFI_system_partition#Format_the_partition","rel":["nofollow"]},"children":[{"type":"text","value":"7"}]}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# pacman -Sy dosfstools\n[root@archlinux ~]# mkfs.fat -F32 /dev/sdb1\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# pacman -Sy dosfstools\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mkfs.fat -F32 /dev/sdb1\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"As for the root partition, it is recommended to use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ext4"}]},{"type":"text","value":" without a journal to\nreduce the reads and writes to the file-system as this is detrimental to the\nflash-based USB drive. "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/Install_Arch_Linux_on_a_USB_key#Installation_tweaks","rel":["nofollow"]},"children":[{"type":"text","value":"8"}]}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# mkfs.ext4 -O \"^has_journal\" /dev/sdb2\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mkfs.ext4 -O "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"^has_journal\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" /dev/sdb2\n"}]}]}]}]},{"type":"element","tag":"h3","props":{"id":"mount-the-partitions-and-bootstrap-the-environment"},"children":[{"type":"text","value":"Mount the Partitions and Bootstrap the Environment"}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# mount /dev/sdb2 /mnt\n[root@archlinux ~]# mkdir -p /mnt/boot/efi\n[root@archlinux ~]# mount /dev/sdb1 /mnt/boot/efi\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mount /dev/sdb2 /mnt\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mkdir -p /mnt/boot/efi\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mount /dev/sdb1 /mnt/boot/efi\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# pacman -S arch-install-scripts\n[root@archlinux ~]# pacstrap /mnt base linux linux-firmware\n[root@archlinux ~]# genfstab -U /mnt >> /mnt/etc/fstab\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# pacman -S arch-install-scripts\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# pacstrap /mnt base linux linux-firmware\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# genfstab -U /mnt "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":">>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" /mnt/etc/fstab\n"}]}]}]}]},{"type":"element","tag":"h3","props":{"id":"configure-the-new-environment"},"children":[{"type":"text","value":"Configure the New Environment"}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# arch-chroot /mnt\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"[root@archlinux ~]# arch-chroot /mnt\n"}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux /]# ln -sf /usr/share/zoneinfo/US/Eastern /etc/localtime\n[root@archlinux /]# hwclock --systohc\n[root@archlinux /]# sed -i 's/#en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen\n[root@archlinux /]# locale-gen\n[root@archlinux /]# echo \"LANG=en_US.UTF-8\" > /etc/locale.conf\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"[root@archlinux /]# ln -sf /usr/share/zoneinfo/US/Eastern /etc/localtime\n[root@archlinux /]# hwclock --systohc\n[root@archlinux /]# sed -i 's/#en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen\n[root@archlinux /]# locale-gen\n[root@archlinux /]# echo \"LANG=en_US.UTF-8\" > /etc/locale.conf\n"}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux /]# hostnamectl set-hostname usb\n[root@archlinux /]# echo \"127.0.0.1 localhost\" >> /etc/hosts\n[root@archlinux /]# echo \"::1 localhost\" >> /etc/hosts\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"[root@archlinux /]# hostnamectl set-hostname usb\n[root@archlinux /]# echo \"127.0.0.1 localhost\" >> /etc/hosts\n[root@archlinux /]# echo \"::1 localhost\" >> /etc/hosts\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Note, one difference here from a standard installation is that the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--removable"}]},{"type":"text","value":" flag is specified when installing the GRUB bootloader.\n"},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/GRUB#UEFI_systems","rel":["nofollow"]},"children":[{"type":"text","value":"10"}]}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux /]# pacman -S grub\n[root@archlinux /]# grub-install --target=x86_64-efi --efi-directory=/boot/efi --removable --recheck\n[root@usb /]# grub-mkconfig -o /boot/grub/grub.cfg\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"[root@archlinux /]# pacman -S grub\n[root@archlinux /]# grub-install --target=x86_64-efi --efi-directory=/boot/efi --removable --recheck\n[root@usb /]# grub-mkconfig -o /boot/grub/grub.cfg\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Shutdown the virtual machine, restart the host machine, and boot the newly\ncreated Arch Linux thumb-drive!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"🎉"}]},{"type":"element","tag":"h2","props":{"id":"side-note"},"children":[{"type":"text","value":"Side-note"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"It was attempted to use the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"controlvm usbattach"}]},{"type":"text","value":" command to pass the USB\ndevice to the guest machine, but this did not work as it expects the virtual\nmachine to already be running, and the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"vb.customize"}]},{"type":"text","value":" option runs prior to\nbooting the machine. "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://www.vagrantup.com/docs/virtualbox/configuration.html#vboxmanage-customizations","rel":["nofollow"]},"children":[{"type":"text","value":"11"}]}]}]},{"type":"element","tag":"pre","props":{"code":"Command: [\"controlvm\", \"060a716b-1965-49e2-bc56-12beed5df716\", \"usbattach36fc9e60-c465-11cf-8056-444553540000\"]\n\nStderr: VBoxManage.exe: error: Machine '060a716b-1965-49e2-bc56-12beed5df716' is not currently running.\n","language":"txt","meta":"","className":"language-txt shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Command: [\"controlvm\", \"060a716b-1965-49e2-bc56-12beed5df716\", \"usbattach36fc9e60-c465-11cf-8056-444553540000\"]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Stderr: VBoxManage.exe: error: Machine '060a716b-1965-49e2-bc56-12beed5df716' is not currently running.\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"references"},"children":[{"type":"text","value":"References"}]},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.docker.com/docker-for-mac/docker-toolbox/","rel":["nofollow"]},"children":[{"type":"text","value":"Docker Desktop on Mac vs. Docker Toolbox"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/moby/hyperkit","rel":["nofollow"]},"children":[{"type":"text","value":"GitHub - HyperKit"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/docker/for-mac/issues/900","rel":["nofollow"]},"children":[{"type":"text","value":"GitHub - Docker for Mac - Issue #900"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://app.vagrantup.com/archlinux/boxes/archlinux","rel":["nofollow"]},"children":[{"type":"text","value":"Vagrant Cloud - Arch Linux"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://antonyjepson.wordpress.com/2012/01/26/quickly-attaching-usb-devices-to-virtualbox-guests-using-vboxmanage/","rel":["nofollow"]},"children":[{"type":"text","value":"Attaching USB Devices to VirtualBox Guests using VBoxManage"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://gist.github.com/dscape/7d829c0c116ef419f963","rel":["nofollow"]},"children":[{"type":"text","value":"GitHub Gist - Vagrant USB Filter"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/EFI_system_partition#Format_the_partition","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Wiki - EFI System Partition - Format Partitions"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/Install_Arch_Linux_on_a_USB_key#Installation_tweaks","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Wiki - Arch Linux on USB - Installation Tweaks"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/Installation_guide","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Wiki - Installation Guide"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/GRUB#UEFI_systems","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Wiki - GRUB - UEFI Systems"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://www.vagrantup.com/docs/virtualbox/configuration.html#vboxmanage-customizations","rel":["nofollow"]},"children":[{"type":"text","value":"Vagrant VBoxManage Customizations "}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"create-an-arch-linux-virtual-machine-with-vagrant","depth":2,"text":"Create an Arch Linux Virtual Machine with Vagrant"},{"id":"install-arch-linux-on-the-usb-drive","depth":2,"text":"Install Arch Linux on the USB Drive","children":[{"id":"partition-the-disk-uefi-with-gpt","depth":3,"text":"Partition the Disk (UEFI with GPT)"},{"id":"format-the-partitions","depth":3,"text":"Format the Partitions"},{"id":"mount-the-partitions-and-bootstrap-the-environment","depth":3,"text":"Mount the Partitions and Bootstrap the Environment"},{"id":"configure-the-new-environment","depth":3,"text":"Configure the New Environment"}]},{"id":"side-note","depth":2,"text":"Side-note"},{"id":"references","depth":2,"text":"References"}]}},"_type":"markdown","_id":"content:articles:persistent-archlinux-usb.md","_source":"content","_file":"articles/persistent-archlinux-usb.md","_stem":"articles/persistent-archlinux-usb","_extension":"md"},{"_path":"/articles/podcast-transcription-whispercpp","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Easily Transcribe Podcasts with Whisper.cpp","description":"If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive whisper.cpp project. This high-performance fork of OpenAI's Whisper can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the Alter Everything podcast.","draft":false,"date":"2024-01-08","tags":["whisper.cpp","ml"],"categories":["programming"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive "},{"type":"element","tag":"a","props":{"href":"https://github.com/ggerganov/whisper.cpp","rel":["nofollow"]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" project. This high-performance fork of "},{"type":"element","tag":"a","props":{"href":"https://github.com/openai/whisper","rel":["nofollow"]},"children":[{"type":"text","value":"OpenAI's Whisper"}]},{"type":"text","value":" can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the "},{"type":"element","tag":"a","props":{"href":"https://podcasts.apple.com/us/podcast/alter-everything/id1356137854","rel":["nofollow"]},"children":[{"type":"text","value":"Alter Everything"}]},{"type":"text","value":" podcast."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive "},{"type":"element","tag":"a","props":{"href":"https://github.com/ggerganov/whisper.cpp","rel":["nofollow"]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" project. This high-performance fork of "},{"type":"element","tag":"a","props":{"href":"https://github.com/openai/whisper","rel":["nofollow"]},"children":[{"type":"text","value":"OpenAI's Whisper"}]},{"type":"text","value":" can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the "},{"type":"element","tag":"a","props":{"href":"https://podcasts.apple.com/us/podcast/alter-everything/id1356137854","rel":["nofollow"]},"children":[{"type":"text","value":"Alter Everything"}]},{"type":"text","value":" podcast."}]},{"type":"element","tag":"h2","props":{"id":"obtain-audio-files"},"children":[{"type":"text","value":"Obtain Audio File(s)"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, let's get the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"wav"}]},{"type":"text","value":" file from YouTube using the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"youtube-dl"}]},{"type":"text","value":" utility. It should be noted that "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" expects "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"wav"}]},{"type":"text","value":" filetypes, and this utility defaults to "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"mp3"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"code":" $ youtube-dl \\\n --extract-audio \\\n --audio-format wav \\\n --output podcast.wav \\\n \"https://www.youtube.com/watch?v=CoUN690wSYQ\"\n","language":"sh","meta":"","className":"language-sh shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" youtube-dl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --extract-audio"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --audio-format"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" wav"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --output"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast.wav"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"https://www.youtube.com/watch?v=CoUN690wSYQ\"\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This file has a 44.1 kHz sample rate, and "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" expects 16 kHz, so let's go ahead and convert that."}]},{"type":"element","tag":"pre","props":{"code":" $ file podcast.wav\npodcast.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz\n\n $ ffmpeg -i podcast.wav -ar 16000 podcast-16khz.wav\n\n $ file podcast-16khz.wav\npodcast-16khz.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 16000 Hz\n\n# NOTE: it looks like it's possible to specify this conversion as a post-process as a\n# flag to the `youtube-dl` command -- I will explore this further next time...\n# youtube-dl --extract-audio --audio-quality 0 --audio-format mp3 --postprocessor-args \"-ar 44100\" %dl%\n","language":"sh","meta":"","className":"language-sh shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" file"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast.wav\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"podcast.wav:"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" RIFF"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ffmpeg"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -i"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast.wav"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -ar"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 16000"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast-16khz.wav\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" file"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast-16khz.wav\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"podcast-16khz.wav:"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" RIFF"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 16000 Hz\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# NOTE: it looks like it's possible to specify this conversion as a post-process as a\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# flag to the `youtube-dl` command -- I will explore this further next time...\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# youtube-dl --extract-audio --audio-quality 0 --audio-format mp3 --postprocessor-args \"-ar 44100\" %dl%\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"build-whispercpp-transcribe-audio"},"children":[{"type":"text","value":"Build "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" & Transcribe Audio"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, let's get the latest version of "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":", download the English Whisper model, and build the example."}]},{"type":"element","tag":"pre","props":{"code":"# Clone the `whisper.cpp` repository\n $ git clone --depth 1 git@github.com:ggerganov/whisper.cpp && cd whisper.cpp\n\n# Download the English Whisper model in `ggml` format\n $ bash ./models/download-ggml-model.sh base.en\n\n# Build the main example\n $ make\n","language":"sh","meta":"","className":"language-sh shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# Clone the `whisper.cpp` repository\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" git"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" clone"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --depth"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" git@github.com:ggerganov/whisper.cpp"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" && "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"cd"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" whisper.cpp\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# Download the English Whisper model in `ggml` format\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" bash"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ./models/download-ggml-model.sh"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" base.en\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# Build the main example\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" make\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And finally, let's transcribe that podcast!"}]},{"type":"element","tag":"pre","props":{"code":" $ ./main \\\n -m ~/workspace/whisper.cpp/models/ggml-base.en.bin \\\n -f ~/Downloads/podcast-16khz.wav \\\n --output-vtt \\\n --output-file out\n\n# whisper_print_timings: load time = 114.71 ms\n# whisper_print_timings: fallbacks = 0 p / 0 h\n# whisper_print_timings: mel time = 692.20 ms\n# whisper_print_timings: sample time = 22278.10 ms / 27893 runs ( 0.80 ms per run)\n# whisper_print_timings: encode time = 10000.75 ms / 55 runs ( 181.83 ms per run)\n# whisper_print_timings: decode time = 331.77 ms / 54 runs ( 6.14 ms per run)\n# whisper_print_timings: batchd time = 45236.73 ms / 27566 runs ( 1.64 ms per run)\n# whisper_print_timings: prompt time = 1921.90 ms / 11832 runs ( 0.16 ms per run)\n# whisper_print_timings: total time = 80709.54 ms\n","language":"sh","meta":"","className":"language-sh shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ./main"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -m"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ~/workspace/whisper.cpp/models/ggml-base.en.bin"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -f"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ~/Downloads/podcast-16khz.wav"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --output-vtt"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --output-file"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" out\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: load time = 114.71 ms\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: fallbacks = 0 p / 0 h\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: mel time = 692.20 ms\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: sample time = 22278.10 ms / 27893 runs ( 0.80 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: encode time = 10000.75 ms / 55 runs ( 181.83 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":12},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: decode time = 331.77 ms / 54 runs ( 6.14 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":13},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: batchd time = 45236.73 ms / 27566 runs ( 1.64 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":14},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: prompt time = 1921.90 ms / 11832 runs ( 0.16 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":15},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: total time = 80709.54 ms\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"A full podcast transcribed in ~80 seconds on an M1 Mac Mini -- not too bad!"}]},{"type":"element","tag":"pre","props":{"code":"# out.vtt\n\n00:00:00.000 --> 00:00:06.480\n >> Hi everyone. We recently launched a short engagement feedback survey for the Alter Everything\n\n00:00:06.480 --> 00:00:11.360\n podcast. Click the link in the episode description wherever you're listening to let us know what\n\n00:00:11.360 --> 00:00:16.320\n you think and help us improve our show.\n\n00:00:16.320 --> 00:00:21.200\n Welcome to Alter Everything, a podcast about data science and analytics culture. I'm Megan\n\n00:00:21.200 --> 00:00:26.440\n Dibble and today I'm talking with Nick Schrock, CTO and founder of Dagster Labs. We discussed\n\n00:00:26.440 --> 00:00:31.560\n data engineering trends, challenges in the field, why he started his company, and what\n\n00:00:31.560 --> 00:00:38.960\n makes him excited about the future of data engineering. Let's get started.\n\n00:00:38.960 --> 00:00:42.720\n >> Hi, Nick. It's great to have you on our show today. Thanks for being here.\n\n00:00:42.720 --> 00:00:43.920\n >> Thanks for having me.\n\n00:00:43.920 --> 00:00:48.280\n >> Yeah. Could you start off by giving an introduction to yourself for our listeners?\n\n00:00:48.280 --> 00:00:52.920\n >> Sure. My name is Nick Schrock. I'm the CTO and founder of Dagster Labs. There's the\n\n00:00:52.920 --> 00:00:59.520\n company behind Dagster, which is a data orchestration framework. Prior to doing this, I was an engineer\n\n00:00:59.520 --> 00:01:05.960\n at Facebook from 2009, 2017. While I was there, I found a team called product infrastructure\n\n00:01:05.960 --> 00:01:09.800\n whose goal was to make our application developers more efficient and productive, and a bunch\n\n00:01:09.800 --> 00:01:13.840\n of open source work came out of that actually, one of which was React, which I had nothing\n\n00:01:13.840 --> 00:01:18.040\n to do with, but actually the CEO of Dagster Labs co-created and I personally co-created\n\n00:01:18.040 --> 00:01:22.640\n GraphQL. So as I like to say, Pete and I were present at the creation of the full hipster\n\n00:01:22.640 --> 00:01:28.680\n stack. I moved on to Facebook in 2017, figuring out what to do next, and this data engineering\n\n00:01:28.680 --> 00:01:32.960\n and data orchestration problem really got me hooked actually quite soon after I left,\n\n00:01:32.960 --> 00:01:36.280\n and the rest is history. I'm sure we'll get into that more.\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"# out.vtt\n\n00:00:00.000 --> 00:00:06.480\n >> Hi everyone. We recently launched a short engagement feedback survey for the Alter Everything\n\n00:00:06.480 --> 00:00:11.360\n podcast. Click the link in the episode description wherever you're listening to let us know what\n\n00:00:11.360 --> 00:00:16.320\n you think and help us improve our show.\n\n00:00:16.320 --> 00:00:21.200\n Welcome to Alter Everything, a podcast about data science and analytics culture. I'm Megan\n\n00:00:21.200 --> 00:00:26.440\n Dibble and today I'm talking with Nick Schrock, CTO and founder of Dagster Labs. We discussed\n\n00:00:26.440 --> 00:00:31.560\n data engineering trends, challenges in the field, why he started his company, and what\n\n00:00:31.560 --> 00:00:38.960\n makes him excited about the future of data engineering. Let's get started.\n\n00:00:38.960 --> 00:00:42.720\n >> Hi, Nick. It's great to have you on our show today. Thanks for being here.\n\n00:00:42.720 --> 00:00:43.920\n >> Thanks for having me.\n\n00:00:43.920 --> 00:00:48.280\n >> Yeah. Could you start off by giving an introduction to yourself for our listeners?\n\n00:00:48.280 --> 00:00:52.920\n >> Sure. My name is Nick Schrock. I'm the CTO and founder of Dagster Labs. There's the\n\n00:00:52.920 --> 00:00:59.520\n company behind Dagster, which is a data orchestration framework. Prior to doing this, I was an engineer\n\n00:00:59.520 --> 00:01:05.960\n at Facebook from 2009, 2017. While I was there, I found a team called product infrastructure\n\n00:01:05.960 --> 00:01:09.800\n whose goal was to make our application developers more efficient and productive, and a bunch\n\n00:01:09.800 --> 00:01:13.840\n of open source work came out of that actually, one of which was React, which I had nothing\n\n00:01:13.840 --> 00:01:18.040\n to do with, but actually the CEO of Dagster Labs co-created and I personally co-created\n\n00:01:18.040 --> 00:01:22.640\n GraphQL. So as I like to say, Pete and I were present at the creation of the full hipster\n\n00:01:22.640 --> 00:01:28.680\n stack. I moved on to Facebook in 2017, figuring out what to do next, and this data engineering\n\n00:01:28.680 --> 00:01:32.960\n and data orchestration problem really got me hooked actually quite soon after I left,\n\n00:01:32.960 --> 00:01:36.280\n and the rest is history. I'm sure we'll get into that more.\n"}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"obtain-audio-files","depth":2,"text":"Obtain Audio File(s)"},{"id":"build-whispercpp-transcribe-audio","depth":2,"text":"Build whisper.cpp & Transcribe Audio"}]}},"_type":"markdown","_id":"content:articles:podcast-transcription-whispercpp.md","_source":"content","_file":"articles/podcast-transcription-whispercpp.md","_stem":"articles/podcast-transcription-whispercpp","_extension":"md"},{"_path":"/articles/quick-tip-rerunning-bash-commands","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Tip: Re-running Bash Commands","description":"Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use sudo for a command that requires\nroot privileges.","date":"2021-09-22","draft":false,"tags":["tip","bash"],"categories":["tips"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sudo"}]},{"type":"text","value":" for a command that requires\nroot privileges."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sudo"}]},{"type":"text","value":" for a command that requires\nroot privileges."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ pacman -Syu\nerror: you cannot perform this operation unless you are root.\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pacman"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -Syu\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"error:"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" you"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" cannot"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" perform"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" this"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" operation"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" unless"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" you"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" are"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" root.\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Well, I have good news for you -- you can easily re-issue a command with the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!!"}]},{"type":"text","value":" designator! Simply type "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sudo"}]},{"type":"text","value":" followed by "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!!"}]},{"type":"text","value":" and you're good to go."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ sudo !!\nsudo pacman -Syu\n[sudo] password for colton:\n:: Synchronizing package databases...\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" !!\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pacman"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -Syu\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[sudo] password "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"for"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" colton:\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"::"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" Synchronizing"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" package"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" databases...\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"--"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Commands that are prefixed with a bang, "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!"}]},{"type":"text","value":", are considered "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Event\nDesignators,"}]},{"type":"text","value":" and are references to your command-line history. You can take a\nlook at your history with the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"history"}]},{"type":"text","value":" command."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ history\n 1021 touch hello_world.txt\n 1022 ls\n 1023 echo \"Here we go again!\"\n 1024 find . -name *.py\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" history\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" 1021"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" touch"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" hello_world.txt\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" 1022"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ls\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" 1023"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" echo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"Here we go again!\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" 1024"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" find"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -name"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" *"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":".py\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"There are many ways to use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!"}]},{"type":"text","value":" in your shell. For example, if you wanted to\nre-issue a specific command in your history, you could use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!n"}]},{"type":"text","value":" where "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"n"}]},{"type":"text","value":" is\nthe number next to the command in your history."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ !1023\necho \"Here we go again!\"\nHere we go again!\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" !1023\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"echo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"Here we go again!\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"Here"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" we"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" go"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" again!\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Or... if you wanted to run the command you issued 4-commands ago, you can use\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!-4"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ !-4\nls\nhello_world.txt\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" !-4\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"ls\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"hello_world.txt\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Or... if you wanted to run the last command that started with the string\n"},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"find"}]},{"type":"text","value":", you can use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!find"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ !find\nfind . -name *.py\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" !find\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"find"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -name"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" *"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":".py\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Be sure to check out the "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Event Designators"}]},{"type":"text","value":" section of the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"bash"}]},{"type":"text","value":" "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"man"}]},{"type":"text","value":" pages\nfor more information!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"--"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"As an aside, for even faster command-line history navigation, be sure to check\nout the excellent "},{"type":"element","tag":"a","props":{"href":"https://github.com/junegunn/fzf","rel":["nofollow"]},"children":[{"type":"text","value":"fzf"}]},{"type":"text","value":" utility by "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"junegunn."}]},{"type":"text","value":"\nOne of the many features of "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"fzf"}]},{"type":"text","value":" is browsing and re-issuing commands from your\ncommand-line history with a fuzzy-finder!"}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:quick-tip-rerunning-bash-commands.md","_source":"content","_file":"articles/quick-tip-rerunning-bash-commands.md","_stem":"articles/quick-tip-rerunning-bash-commands","_extension":"md"},{"_path":"/articles/reset-ipmi-password-from-host-os","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Reset IPMI Credentials from the Host OS","description":"If you ever find yourself locked out of the Intelligent Platform Management Interface (IPMI) of a server, these\ninstructions will guide your through the process of resetting the credentials to their default values from the host\noperating system.","date":"2021-12-27","tags":["homelab","supermicro","truenas"],"categories":["homelab"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you ever find yourself locked out of the Intelligent Platform Management Interface (IPMI) of a server, these\ninstructions will guide your through the process of resetting the credentials to their default values from the host\noperating system."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you ever find yourself locked out of the Intelligent Platform Management Interface (IPMI) of a server, these\ninstructions will guide your through the process of resetting the credentials to their default values from the host\noperating system."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you are using an operating system like TrueNAS -- good news! It's possible to reset the IPMI password directly from\nthe web interface. This is done by navigating to "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Network > IPMI"}]},{"type":"text","value":", and simply entering a new value in the "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"IPMI\nPassword Reset"}]},{"type":"text","value":" field."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you are using some other OS that doesn't have this feature, you can achieve similar results by using the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ipmitool"}]},{"type":"text","value":"\ncommand-line utility."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, you'll want to determine the user ID associated with the user for whom you'd like to reset the password."}]},{"type":"element","tag":"pre","props":{"code":"# ipmitool user list\nID Name Callin Link Auth IPMI Msg Channel Priv Limit\n1 true false false Unknown (0x00)\n2 ADMIN true false false Unknown (0x00)\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"# ipmitool user list\nID Name Callin Link Auth IPMI Msg Channel Priv Limit\n1 true false false Unknown (0x00)\n2 ADMIN true false false Unknown (0x00)\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In this case, we will be resetting the password for "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"ADMIN"}]},{"type":"text","value":" who has a user ID of "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"2"}]},{"type":"text","value":". Then we'll assign the new\npassword like so:"}]},{"type":"element","tag":"pre","props":{"code":"# ipmitool user set password 2 \n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"# ipmitool user set password 2 \n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And you should be good to go!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"..."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Alternatively, if you'd like to factory reset the baseboard management controller (BMC), which will reset the IPMI\ncredentials to their default value, you can issue the following command."}]},{"type":"element","tag":"pre","props":{"code":"# ipmitool raw 0x3c 0x40\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"# ipmitool raw 0x3c 0x40\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Where "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"0x3c"}]},{"type":"text","value":" is the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":""}]},{"type":"text","value":" argument, a.k.a. the network function code that defines the functional routing for\nmessages, and "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"0x40"}]},{"type":"text","value":" is the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":""}]},{"type":"text","value":". According to section 5.1 of the "},{"type":"element","tag":"a","props":{"href":"https://www.intel.com/content/dam/www/public/us/en/documents/product-briefs/ipmi-second-gen-interface-spec-v2-rev1-1.pdf","rel":["nofollow"]},"children":[{"type":"text","value":"IPMI interface\nspecification"}]},{"type":"text","value":",\n"},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"netfn"}]},{"type":"text","value":" codes ranging from 0x30 to 0x3F are reserved for vendor specific functions. I searched around for some\nSupermicro references on these vendor specific network functions without much luck other than various "},{"type":"element","tag":"a","props":{"href":"https://www.supermicro.com/support/faqs/faq.cfm?faq=15448","rel":["nofollow"]},"children":[{"type":"text","value":"support\nresponses"}]},{"type":"text","value":" on how to reset a device. Bummer!"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:reset-ipmi-password-from-host-os.md","_source":"content","_file":"articles/reset-ipmi-password-from-host-os.md","_stem":"articles/reset-ipmi-password-from-host-os","_extension":"md"},{"_path":"/articles/ssh-ed25519-sk-yubikey","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Configuring a YubiKey for use with OpenSSH","description":"YubiKey's are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" ed25519-sk key type that supports FIDO compliant hardware keys.","draft":false,"date":"2024-06-09","tags":["unix","configurations"],"categories":["tooling","tips"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://www.yubico.com/","rel":["nofollow"]},"children":[{"type":"text","value":"YubiKey's"}]},{"type":"text","value":" are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ed25519-sk"}]},{"type":"text","value":" key type that supports FIDO compliant hardware keys."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://www.yubico.com/","rel":["nofollow"]},"children":[{"type":"text","value":"YubiKey's"}]},{"type":"text","value":" are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ed25519-sk"}]},{"type":"text","value":" key type that supports FIDO compliant hardware keys."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In "},{"type":"element","tag":"a","props":{"href":"https://www.openssh.com/txt/release-8.2","rel":["nofollow"]},"children":[{"type":"text","value":"release 8.2 of OpenSSH"}]},{"type":"text","value":" support for FIDO devices was added with public key types \"ecdsa-sk\" and \"ed25519-sk\" (-sk standing for \"security key\"). This key type is supported by YubiKey's with firmware version 5.2.3 or higher."}]},{"type":"element","tag":"blockquote","props":{},"children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This release adds support for FIDO/U2F hardware authenticators to OpenSSH. U2F/FIDO are open standards for inexpensive two-factor authentication hardware that are widely used for website authentication. In OpenSSH FIDO devices are supported by new public key types \"ecdsa-sk\" and \"ed25519-sk\", along with corresponding certificate types."}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Let's get started by installing the latest version of OpenSSH via "},{"type":"element","tag":"a","props":{"href":"https://brew.sh/","rel":["nofollow"]},"children":[{"type":"text","value":"Homebrew"}]},{"type":"text","value":", along with the YubiKey Manager (ykman) CLI. The version of OpenSSH included with macOS is not compatible."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"$ brew install openssh ykman\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" brew"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" openssh"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ykman\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, let's confirm that our YubiKey has a firmware that is greater than 5.2.3:"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"$ ykman list\nYubiKey 5Ci (5.4.3) [OTP+FIDO+CCID]\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ykman"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"YubiKey"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 5Ci"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (5.4.3) [OTP+FIDO+CCID]\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Next, we'll go ahead and enable a pin on our device via the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"change-pin"}]},{"type":"text","value":" command, as this a requirement for our use."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"$ ykman fido access change-pin\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ykman"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" fido"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" access"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" change-pin\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And last, we'll generate the key on our device!"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"$ ssh-keygen -t ed25519-sk -O resident\nGenerating public/private ed25519-sk key pair.\nYou may need to touch your authenticator to authorize key generation.\n...\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ssh-keygen"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -t"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ed25519-sk"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -O"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" resident\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"Generating"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" public/private"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ed25519-sk"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" key"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pair.\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"You"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" may"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" need"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" to"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" touch"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" your"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" authenticator"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" to"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" authorize"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" key"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" generation.\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"...\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"We specify "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"resident"}]},{"type":"text","value":" to indicate that the key handle is to be stored on the YubiKey itself, since we will be using this device with multiple computers."}]},{"type":"element","tag":"pre","props":{"className":"language-txt shiki shiki-themes github-light","code":"resident\n Indicate that the key handle should be stored on the FIDO\n authenticator itself. This makes it easier to use the\n authenticator on multiple computers. Resident keys may be\n supported on FIDO2 authenticators and typically require that a PIN\n be set on the authenticator prior to generation. Resident keys\n may be loaded off the authenticator using ssh-add(1). Storing\n both parts of a key on a FIDO authenticator increases the\n likelihood of an attacker being able to use a stolen authenticator\n device.\n","language":"txt","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"resident\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" Indicate that the key handle should be stored on the FIDO\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" authenticator itself. This makes it easier to use the\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" authenticator on multiple computers. Resident keys may be\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" supported on FIDO2 authenticators and typically require that a PIN\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" be set on the authenticator prior to generation. Resident keys\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" may be loaded off the authenticator using ssh-add(1). Storing\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" both parts of a key on a FIDO authenticator increases the\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" likelihood of an attacker being able to use a stolen authenticator\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" device.\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And that's all it takes -- simple enough. Now, when interacting with "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"ssh"}]},{"type":"text","value":" or "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"git"}]},{"type":"text","value":" you will be prompted to touch the YubiKey to bring that little bit of physical 2FA."}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:ssh-ed25519-sk-yubikey.md","_source":"content","_file":"articles/ssh-ed25519-sk-yubikey.md","_stem":"articles/ssh-ed25519-sk-yubikey","_extension":"md"},{"_path":"/articles/unit-testing-micropython-with-mocks","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Unit Testing in MicroPython with Mocks","description":"Unit testing code for embedded systems can be challenging. While it's possible\nto leverage emulators, write side-effect free code, or run tests on the\nhardware itself, it's often easiest to unit test the code on your personal\ncomputer with mocked hardware functionality.","date":"2020-02-07","draft":false,"tags":["micropython","testing","mocks","tutorial"],"categories":["python","embedded"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Unit testing code for embedded systems can be challenging. While it's possible\nto leverage emulators, write side-effect free code, or run tests on the\nhardware itself, it's often easiest to unit test the code on your personal\ncomputer with mocked hardware functionality."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Unit testing code for embedded systems can be challenging. While it's possible\nto leverage emulators, write side-effect free code, or run tests on the\nhardware itself, it's often easiest to unit test the code on your personal\ncomputer with mocked hardware functionality."}]},{"type":"element","tag":"h1","props":{"id":"mocking"},"children":[{"type":"text","value":"Mocking"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Mocks allow us to replace the hardware interfacing functionality under-the-hood\nwith predefined results and side-effects. For example, if there is a piece of\nlogic that retrieves values from an accelerometer to get a device's\norientation, it would be possible to mock the returned values of the\naccelerometer -- allowing us to run the unit tests on a device that does not\nhave an accelerometer sensor installed."}]},{"type":"element","tag":"h1","props":{"id":"a-micropython-mocking-example"},"children":[{"type":"text","value":"A MicroPython Mocking Example"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In this example, we will be unit testing a module named "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"time_logger"}]},{"type":"text","value":", that\ndepends on the MicroPython library "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime"}]},{"type":"text","value":" to log the most recent Epoch time to\na file."}]},{"type":"element","tag":"pre","props":{"className":"language-python shiki shiki-themes github-light","code":"# time_logger.py\n\nclass TimeLogger(object):\n\n def save_time(self):\n \"\"\" Overwrite a file with the most recent Epoch timestamp from `utime`\n \"\"\"\n with open(\"LAST_KNOWN_TIME\", \"w+\") as f:\n f.write(str(utime.time()))\n","language":"python","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# time_logger.py\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"class"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" TimeLogger"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"object"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" def"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" save_time"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(self):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"\"\" Overwrite a file with the most recent Epoch timestamp from `utime`\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"\"\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" with"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" open"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"LAST_KNOWN_TIME\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"w+\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"as"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" f:\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" f.write("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"str"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(utime.time()))\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, because the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime"}]},{"type":"text","value":" module is not installed on the machine that the unit\ntests on, we must mock "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime"}]},{"type":"text","value":" module before importing "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"time_logger"}]},{"type":"text","value":" in our\nunit test file."}]},{"type":"element","tag":"pre","props":{"className":"language-python shiki shiki-themes github-light","code":"# test_time_logger.py\n\nimport unittest\n\nfrom unittest.mock import MagicMock\n\nsys.modules['utime'] = MagicMock()\nfrom time_logger import TimeLogger\n","language":"python","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# test_time_logger.py\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" unittest\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" unittest.mock "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" MagicMock\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"sys.modules["}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'utime'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"] "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" MagicMock()\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" time_logger "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" TimeLogger\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, we can write a test that patches the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime.time"}]},{"type":"text","value":" functionality so that\nit returns a value of our choosing -- in this case, "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"1234"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-python shiki shiki-themes github-light","code":"class TestTimeLogger(unittest.TestCase):\n\n def test_save_time(self):\n \"\"\" Verify that the Epoch time is written to file\n \"\"\"\n with unittest.mock.patch(\"utime.time\", return_value=1234):\n t = TimeLogger()\n t.save_time()\n with open(\"LAST_KNOWN_TIME\") as f:\n self.assertEqual(\"1234\", f.read())\n","language":"python","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"class"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" TestTimeLogger"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"unittest"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"TestCase"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" def"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" test_save_time"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(self):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"\"\" Verify that the Epoch time is written to file\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"\"\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" with"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" unittest.mock.patch("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"utime.time\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"return_value"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"1234"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" t "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" TimeLogger()\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" t.save_time()\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" with"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" open"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"LAST_KNOWN_TIME\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"as"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" f:\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" self"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":".assertEqual("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"1234\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", f.read())\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Now, when the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"save_time"}]},{"type":"text","value":" method gets the latest time from "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime.time()"}]},{"type":"text","value":", the\nvalue will be patched to return "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"1234"}]},{"type":"text","value":". That value will be written to a file,\nand our unit test will pass!"}]},{"type":"element","tag":"h2","props":{"id":"references"},"children":[{"type":"text","value":"References"}]},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.python.org/3/library/unittest.html","rel":["nofollow"]},"children":[{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"unittest"}]},{"type":"text","value":" — Unit testing framework"}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"references","depth":2,"text":"References"}]}},"_type":"markdown","_id":"content:articles:unit-testing-micropython-with-mocks.md","_source":"content","_file":"articles/unit-testing-micropython-with-mocks.md","_stem":"articles/unit-testing-micropython-with-mocks","_extension":"md"},{"_path":"/articles/vim-fugitive-gpg-pinentry","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Using pinentry-mac to sign commits from vim-fugitive","description":"In order to sign git commits from within Vim using a plugin like tpope/vim-fugitive, it is necessary to configure the gpg-agent to use a GUI based pinentry-program.","draft":false,"date":"2024-05-11","tags":["vim","tip"],"categories":["tooling","tips"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In order to sign git commits from within Vim using a plugin like "},{"type":"element","tag":"a","props":{"href":"https://github.com/tpope/vim-fugitive","rel":["nofollow"]},"children":[{"type":"text","value":"tpope/vim-fugitive"}]},{"type":"text","value":", it is necessary to configure the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"gpg-agent"}]},{"type":"text","value":" to use a GUI based "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-program"}]},{"type":"text","value":"."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In order to sign git commits from within Vim using a plugin like "},{"type":"element","tag":"a","props":{"href":"https://github.com/tpope/vim-fugitive","rel":["nofollow"]},"children":[{"type":"text","value":"tpope/vim-fugitive"}]},{"type":"text","value":", it is necessary to configure the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"gpg-agent"}]},{"type":"text","value":" to use a GUI based "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-program"}]},{"type":"text","value":"."}]},{"type":"element","tag":"h2","props":{"id":"preface"},"children":[{"type":"text","value":"Preface"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The man, the myth, the legend, Timothy Popallopollis himself "},{"type":"element","tag":"a","props":{"href":"https://github.com/tpope/vim-fugitive/issues/846#issuecomment-253816577","rel":["nofollow"]},"children":[{"type":"text","value":"recommends"}]},{"type":"text","value":" configuring your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"gpg-agent"}]},{"type":"text","value":" to use a GUI based "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-program"}]},{"type":"text","value":". On macOS this can be done quite by simply installing "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-mac"}]},{"type":"text","value":", and updating your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"gpg-agent.conf"}]},{"type":"text","value":"."}]},{"type":"element","tag":"h2","props":{"id":"configuration"},"children":[{"type":"text","value":"Configuration"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First things first, let's install the pinentry program."}]},{"type":"element","tag":"pre","props":{"code":"$ brew install pinentry-mac\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" brew"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pinentry-mac\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, all we need to do is set the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-program"}]},{"type":"text","value":" option in your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"~/.gnupg/gpg-agent.conf"}]},{"type":"text","value":" file."}]},{"type":"element","tag":"pre","props":{"code":"default-cache-ttl 600\nmax-cache-ttl 7200\npinentry-program /opt/homebrew/bin/pinentry-mac\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"default-cache-ttl 600\nmax-cache-ttl 7200\npinentry-program /opt/homebrew/bin/pinentry-mac\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If your don't know the path to your pinentry program, you can throw down a quick "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"which"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"code":"$ which pinentry-mac\n/opt/homebrew/bin/pinentry-mac\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" which"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pinentry-mac\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"/opt/homebrew/bin/pinentry-mac\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Or use your Homebrew prefix."}]},{"type":"element","tag":"pre","props":{"code":"$ echo $(brew --prefix)/bin/pinentry-mac\n/opt/homebrew/bin/pinentry-mac\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" echo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" $("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"brew"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --prefix"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"/bin/pinentry-mac\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"/opt/homebrew/bin/pinentry-mac\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"But that's all it takes. Now, you should be prompted to enter your gpg pin in an external window when signing commits from vim."}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"preface","depth":2,"text":"Preface"},{"id":"configuration","depth":2,"text":"Configuration"}]}},"_type":"markdown","_id":"content:articles:vim-fugitive-gpg-pinentry.md","_source":"content","_file":"articles/vim-fugitive-gpg-pinentry.md","_stem":"articles/vim-fugitive-gpg-pinentry","_extension":"md"}],"navigation":[{"title":"Articles","_path":"/articles","children":[{"title":"Upgrading the Firmware on the PCEngines APU2","_path":"/articles/apu2-firmware-upgrade"},{"title":"Docker Volume Permissions with SELinux","_path":"/articles/docker-selinux-volumes"},{"title":"Exploring the Digital Ocean `doctl` Utility","_path":"/articles/doctl"},{"title":"Impressions of Fennel with Hammerspoon","_path":"/articles/fennel-initial-exploration"},{"title":"Migrate to TrueNAS Scale from TrueNAS Core","_path":"/articles/migrate-truenas-from-core-to-scale"},{"title":"How To Add an RSS Feed to a Nuxt Website","_path":"/articles/nuxt-content-rss-feed"},{"title":"This Website Has Been Migrated to Nuxt 3 🎉","_path":"/articles/nuxt-v3-migration"},{"title":"Create a Persistent Arch Linux Bootable USB with Vagrant","_path":"/articles/persistent-archlinux-usb"},{"title":"Easily Transcribe Podcasts with Whisper.cpp","_path":"/articles/podcast-transcription-whispercpp"},{"title":"Tip: Re-running Bash Commands","_path":"/articles/quick-tip-rerunning-bash-commands"},{"title":"Reset IPMI Credentials from the Host OS","_path":"/articles/reset-ipmi-password-from-host-os"},{"title":"Configuring a YubiKey for use with OpenSSH","_path":"/articles/ssh-ed25519-sk-yubikey"},{"title":"Unit Testing in MicroPython with Mocks","_path":"/articles/unit-testing-micropython-with-mocks"},{"title":"Using pinentry-mac to sign commits from vim-fugitive","_path":"/articles/vim-fugitive-gpg-pinentry"}]}]} \ No newline at end of file diff --git a/api/_content/cache.1727638383380.json b/api/_content/cache.1727638383380.json new file mode 100644 index 00000000..2a985fb7 --- /dev/null +++ b/api/_content/cache.1727638383380.json @@ -0,0 +1 @@ +{"generatedAt":1727638397468,"generateTime":573,"contents":[{"_path":"/articles/apu2-firmware-upgrade","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Upgrading the Firmware on the PCEngines APU2","description":"I've had a PCEngines APU2 gathering dust for a\nfew years, and have recently decided to dust it off.","date":"2019-12-21","draft":false,"tags":["pcengine","apu"],"categories":["linux"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I've had a "},{"type":"element","tag":"a","props":{"href":"https://pcengines.ch/apu2.htm","rel":["nofollow"]},"children":[{"type":"text","value":"PCEngines APU2"}]},{"type":"text","value":" gathering dust for a\nfew years, and have recently decided to dust it off."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Since the last time the device has been powered on, there have been many great\nimprovements to the firmware, and it was very-much due for an upgrade. The\nfollowing steps outline how the firmware was upgraded on the APU from the\nalready-installed operating system -- CentOS."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I've had a "},{"type":"element","tag":"a","props":{"href":"https://pcengines.ch/apu2.htm","rel":["nofollow"]},"children":[{"type":"text","value":"PCEngines APU2"}]},{"type":"text","value":" gathering dust for a\nfew years, and have recently decided to dust it off."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Since the last time the device has been powered on, there have been many great\nimprovements to the firmware, and it was very-much due for an upgrade. The\nfollowing steps outline how the firmware was upgraded on the APU from the\nalready-installed operating system -- CentOS."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, we will connect to the device over the serial port"}]},{"type":"element","tag":"pre","props":{"code":"screen /dev/tty.usbserial 115200\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"screen /dev/tty.usbserial 115200\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, we will install the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"flashrom"}]},{"type":"text","value":" utility that is needed to update the\nfirmware. Because it is not available in the default "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"yum"}]},{"type":"text","value":" repositories, we\nwill enable the "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Extra Packages for Enterprise Linux"}]},{"type":"text","value":" (EPEL) repository before\ninstallation."}]},{"type":"element","tag":"pre","props":{"code":"sudo yum install epel-release\nsudo yum install flashrom\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" yum"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" epel-release\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" yum"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" flashrom\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Next, we will download the latest version of the firmware that is compatible\nwith the APU2 device from the PC Engines release website:\n"},{"type":"element","tag":"a","props":{"href":"https://pcengines.github.io/","rel":["nofollow"]},"children":[{"type":"text","value":"https://pcengines.github.io/"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"code":"curl -O https://3mdeb.com/open-source-firmware/pcengines/apu2/apu2_v4.11.0.1.rom\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"curl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -O"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" https://3mdeb.com/open-source-firmware/pcengines/apu2/apu2_v4.11.0.1.rom\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And finally, we will flash the firmware..."}]},{"type":"element","tag":"pre","props":{"code":"sudo flashrom -w apu2_v4.11.0.1.rom -p internal:boardmismatch=force\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" flashrom"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -w"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" apu2_v4.11.0.1.rom"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -p"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" internal:boardmismatch=force\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"strong","props":{},"children":[{"type":"text","value":"References:"}]}]},{"type":"element","tag":"ul","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://pcengines.ch/apu2.htm","rel":["nofollow"]},"children":[{"type":"text","value":"https://pcengines.ch/apu2.htm"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://pcengines.github.io/","rel":["nofollow"]},"children":[{"type":"text","value":"https://pcengines.github.io/"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/pcengines/apu2-documentation/blob/master/docs/firmware_flashing.md","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/pcengines/apu2-documentation/blob/master/docs/firmware_flashing.md"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/pcengines/apu2-documentation/blob/master/docs/cold_reset.md","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/pcengines/apu2-documentation/blob/master/docs/cold_reset.md"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/elad/openbsd-apu2","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/elad/openbsd-apu2"}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:apu2-firmware-upgrade.md","_source":"content","_file":"articles/apu2-firmware-upgrade.md","_extension":"md"},{"_path":"/articles/docker-selinux-volumes","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Docker Volume Permissions with SELinux","description":"Unfamiliar with running Docker on a SELinux enabled system, I found myself\nrunning into a bunch of file permission errors while creating volumes.","date":"2019-12-26","draft":false,"tags":["docker","selinux"],"categories":["linux"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Unfamiliar with running Docker on a SELinux enabled system, I found myself\nrunning into a bunch of file permission errors while creating volumes."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Unfamiliar with running Docker on a SELinux enabled system, I found myself\nrunning into a bunch of file permission errors while creating volumes."}]},{"type":"element","tag":"pre","props":{"code":"mkdir: can't create directory '/data': Permission denied\n","language":"txt","meta":"","className":"language-txt shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"mkdir: can't create directory '/data': Permission denied\n"}]}]}]}]},{"type":"element","tag":"hr","props":{},"children":[]},{"type":"element","tag":"pre","props":{"code":"$ docker info --format '{{json .SecurityOptions}}'\n[\n \"name=seccomp,profile=/etc/docker/seccomp.json\",\n \"name=selinux\"\n]\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" docker"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" info"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --format"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" '{{json .SecurityOptions}}'\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"name=seccomp,profile=/etc/docker/seccomp.json\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"name=selinux\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"It turns out that this can be resolved by appending the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":":z"}]},{"type":"text","value":" flag to the volume\nmappings in the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"docker-compose.yml"}]},{"type":"text","value":" file, indicating that the volume content\nis shared."}]},{"type":"element","tag":"pre","props":{"code":"services:\n server:\n volumes:\n - ./data:/data:z\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"services:\n server:\n volumes:\n - ./data:/data:z\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"From the Docker documentation:"}]},{"type":"element","tag":"blockquote","props":{},"children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"z"}]},{"type":"text","value":" option tells Docker that two containers share the volume content. As\na result, Docker labels the content with a shared content label. Shared\nvolume labels allow all containers to read/write content."}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"strong","props":{},"children":[{"type":"text","value":"References"}]}]},{"type":"element","tag":"ul","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.docker.com/engine/reference/commandline/info/","rel":["nofollow"]},"children":[{"type":"text","value":"Docker Docs: Docker Info"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.docker.com/engine/reference/commandline/run/#mount-volumes-from-container---volumes-from","rel":["nofollow"]},"children":[{"type":"text","value":"Docker Docs: Mounting Volumes"}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:docker-selinux-volumes.md","_source":"content","_file":"articles/docker-selinux-volumes.md","_extension":"md"},{"_path":"/articles/doctl","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Exploring the Digital Ocean `doctl` Utility","description":"I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean doctl command line utility.\nThis proved to be an extremely easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future.","date":"2023-01-01","tags":["linux","digital-ocean"],"categories":["linux"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"doctl"}]},{"type":"text","value":" command line utility.\nThis proved to be an "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"extremely"}]},{"type":"text","value":" easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"doctl"}]},{"type":"text","value":" command line utility.\nThis proved to be an "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"extremely"}]},{"type":"text","value":" easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"To start things off, I had to install and setup authentication to Digital Ocean. Doing\nthis on my Mac machine, I opted to use "},{"type":"element","tag":"a","props":{"href":"https://brew.sh/","rel":["nofollow"]},"children":[{"type":"text","value":"Homebrew"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"# install `doctl`\nbrew install doctl\n\n# setup authentication\ndoctl auth init\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# install `doctl`\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"brew"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" doctl\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# setup authentication\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" auth"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" init\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"While the online "},{"type":"element","tag":"a","props":{"href":"https://docs.digitalocean.com/reference/doctl/reference/compute/droplet/create/","rel":["nofollow"]},"children":[{"type":"text","value":"documentation"}]},{"type":"text","value":" is fantastic, I instead found myself mostly referencing the outputs of "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--help"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute droplet create --help\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" droplet"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" create"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --help\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I had to find the image name of the version of Ubuntu I wanted to install:"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute image list --public | grep ubuntu-22\n\n# 118857366 22.04 (LTS) x64 snapshot Ubuntu ubuntu-22-04-x64 true 7\n# 119383150 22.10 x64 snapshot Ubuntu ubuntu-22-10-x64 true 7\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" image"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --public"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" |"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" grep"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ubuntu-22\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# 118857366 22.04 (LTS) x64 snapshot Ubuntu ubuntu-22-04-x64 true 7\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# 119383150 22.10 x64 snapshot Ubuntu ubuntu-22-10-x64 true 7\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And also the slug of the compute size:"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute size list\n\n# Slug Description Memory VCPUs Disk Price Monthly Price Hourly\n# s-1vcpu-512mb-10gb Basic 512 1 10 4.00 0.005950\n# s-1vcpu-1gb Basic 1024 1 25 6.00 0.008930\n# s-1vcpu-1gb-amd Basic AMD 1024 1 25 7.00 0.010420\n# s-1vcpu-1gb-intel Basic Intel 1024 1 25 7.00 0.010420\n# s-1vcpu-2gb Basic 2048 1 50 12.00 0.017860\n# s-1vcpu-2gb-amd Basic AMD 2048 1 50 14.00 0.020830\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" size"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# Slug Description Memory VCPUs Disk Price Monthly Price Hourly\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-512mb-10gb Basic 512 1 10 4.00 0.005950\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-1gb Basic 1024 1 25 6.00 0.008930\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-1gb-amd Basic AMD 1024 1 25 7.00 0.010420\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-1gb-intel Basic Intel 1024 1 25 7.00 0.010420\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-2gb Basic 2048 1 50 12.00 0.017860\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-2gb-amd Basic AMD 2048 1 50 14.00 0.020830\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I've also configured a few SSH keys with Digital Ocean, and I can have the key (specified by ID) provisioned to the machine using the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--ssh-keys"}]},{"type":"text","value":" flag."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute ssh-key list\n\n# ID Name FingerPrint\n# 1234 mini \n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ssh-key"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# ID Name FingerPrint\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# 1234 mini \n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Also, I wanted to install a few packages to the box upon creation, this can be done easily with the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--user-data-file"}]},{"type":"text","value":" flag to run an initialization script."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"echo 'apt install -y imagemagick zip' > bootstrap.sh\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"echo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 'apt install -y imagemagick zip'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" >"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" bootstrap.sh\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Putting it all together, here is the simple command for creating a small compute instance!"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute droplet create \\\n --image ubuntu-22-10-x64 \\\n --size s-1vcpu-512mb-10gb \\\n --region nyc1 \\\n --ssh-keys 1234 \\\n --user-data-file boostrap.sh \\\n ephemeral\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" droplet"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" create"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --image"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ubuntu-22-10-x64"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --size"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" s-1vcpu-512mb-10gb"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --region"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" nyc1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --ssh-keys"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1234"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --user-data-file"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" boostrap.sh"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ephemeral\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Finally, I can connect, do my thing, and destroy the instance."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute ssh ephemeral\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ssh"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ephemeral\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute droplet delete --force ephemeral\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" droplet"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" delete"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --force"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ephemeral\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"All-in-all, I was up and running in about 20 minutes. What a handy utility!"}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:doctl.md","_source":"content","_file":"articles/doctl.md","_extension":"md"},{"_path":"/articles/fennel-initial-exploration","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Impressions of Fennel with Hammerspoon","description":"A while back I read an introductory book on Lisp programming titled, \"The Little\nSchemer\". This book opened my mind to new (to me) programming paradigms, and left me\nwith a strong desire to find a way to incorporate Lisp programming into my every day\nlife. It took some time, but I believe I've found what I've been looking for: Fennel.","draft":false,"date":"2023-10-22","tags":["lisp","hammerspoon","fennel"],"categories":["lisp"],"cover_image":"/images/dall-e-fennel-hammer.jpeg","excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"A while back I read an introductory book on Lisp programming titled, \"The Little\nSchemer\". This book opened my mind to new (to me) programming paradigms, and left me\nwith a strong desire to find a way to incorporate Lisp programming into my every day\nlife. It took some time, but I believe I've found what I've been looking for: Fennel."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"A while back I read an introductory book on Lisp programming titled, \"The Little\nSchemer\". This book opened my mind to new (to me) programming paradigms, and left me\nwith a strong desire to find a way to incorporate Lisp programming into my every day\nlife. It took some time, but I believe I've found what I've been looking for: Fennel."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The "},{"type":"element","tag":"a","props":{"href":"https://fennel-lang.org/","rel":["nofollow"]},"children":[{"type":"text","value":"Fennel"}]},{"type":"text","value":" programming language is a dialect of Lisp that boasts compatibility with\nLua, and it just so happens that two of my favorite applications are configured with\nexactly that language: "},{"type":"element","tag":"a","props":{"href":"https://www.hammerspoon.org/","rel":["nofollow"]},"children":[{"type":"text","value":"Hammerspoon"}]},{"type":"text","value":", and "},{"type":"element","tag":"a","props":{"href":"https://neovim.io/","rel":["nofollow"]},"children":[{"type":"text","value":"Neovim"}]},{"type":"text","value":"."}]},{"type":"element","tag":"h2","props":{"id":"initial-observations"},"children":[{"type":"text","value":"Initial Observations"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"To initially explore Fennel, I wanted to start small. My Hammerspoon configuration\nconsists of 7 "},{"type":"element","tag":"a","props":{"href":"https://github.com/cmpadden/dotfiles/tree/795749fa17e1310bb001bb7deaa22be8689f0027/hammerspoon/.hammerspoon/modules","rel":["nofollow"]},"children":[{"type":"text","value":"modules"}]},{"type":"text","value":" that I use for operations such as: launching applications,\nmanaging windows, keeping my computer from going to sleep, and general operating system\nautomation. So the plan is to translate these modules into Fennel, while maintaining\nwithout breaking the existing functionality. However, at this point, I wasn't even sure\nhow to embed Fennel into my project..."}]},{"type":"element","tag":"h2","props":{"id":"integrating-fennel-with-hammerspoon"},"children":[{"type":"text","value":"Integrating Fennel with Hammerspoon"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"While official documentation exists describing how to "},{"type":"element","tag":"a","props":{"href":"https://fennel-lang.org/setup#embedding-fennel","rel":["nofollow"]},"children":[{"type":"text","value":"embed fennel"}]},{"type":"text","value":" into your\nproject; it didn't provide me with enough clarity to know my next steps on integrating\nit with Hammerspoon. I found a few resources online demonstrating how to extend the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"package.path"}]},{"type":"text","value":" and "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"package.cpath"}]},{"type":"text","value":" properties in Lua, but I was unable to get this to\nwork."}]},{"type":"element","tag":"ul","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://blog.exupero.org/hammerspoon-with-fennel/","rel":["nofollow"]},"children":[{"type":"text","value":"https://blog.exupero.org/hammerspoon-with-fennel/"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/Hammerspoon/hammerspoon/issues/2377#issuecomment-636331435","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/Hammerspoon/hammerspoon/issues/2377#issuecomment-636331435"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/agzam/spacehammer/blob/master/init.lua","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/agzam/spacehammer/blob/master/init.lua"}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Ultimately, I opted to include the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"fennel.lua"}]},{"type":"text","value":" file to my Hammerspoon configuration,\nand while not ideal, it does make the configuration nicely self-contained. I'll leave it\nas a future task to include the module installed with LuaRocks."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"With Fennel now included in my Hammerspoon configuration, all I need to do is configure\nthe "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"fennel.path"}]},{"type":"text","value":" to point to the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"*.fnl"}]},{"type":"text","value":" files in the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":".hammerspoon/"}]},{"type":"text","value":" directory, and\nttranslating these modules can begin!"}]},{"type":"element","tag":"pre","props":{"className":"language-lua shiki shiki-themes github-light","code":"-- init.lua\n\nlocal fennel = require('fennel')\n\nfennel.path = package.path .. \";\" .. os.getenv(\"HOME\") .. \"/.hammerspoon/?.fnl\"\n\ntable.insert(package.loaders or package.searchers, fennel.searcher)\n\nrequire 'main'\n","language":"lua","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"-- init.lua\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"local"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" fennel "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" require"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'fennel'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"fennel."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"path"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" package.path"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" .."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \";\" "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":".."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" os.getenv"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"HOME\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":".."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"/.hammerspoon/?.fnl\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"table.insert"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"package.loaders"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" or"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" package.searchers"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", fennel."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"searcher"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"require"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 'main'\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"translating-lua-to-fennel"},"children":[{"type":"text","value":"Translating Lua to Fennel"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"As a Fennel novice, I was happy to see that the Fennel project provides an online\ncross-compiler for Lua and Fennel called "},{"type":"element","tag":"a","props":{"href":"https://fennel-lang.org/see","rel":["nofollow"]},"children":[{"type":"text","value":"anti-fennel"}]},{"type":"text","value":", and while it can generate some\nstrange-looking Fennel code, it was an extremely useful tool for me to get\nup-and-running right away. For example, by pasting the simple "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sleep"}]},{"type":"text","value":" function\nfrom the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"helpers"}]},{"type":"text","value":" module into the compiler:"}]},{"type":"element","tag":"pre","props":{"className":"language-lua shiki shiki-themes github-light","code":"function sleep(ms)\n os.execute(\"sleep \" .. tonumber(ms) / 1000)\nend\n","language":"lua","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"function"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" sleep"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(ms)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" os.execute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"sleep \" "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":".."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" tonumber"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(ms) "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"/"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1000"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"end\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"className":"language-lisp shiki shiki-themes github-light","code":"(fn sleep [ms]\n (os.execute (.. \"sleep \" (/ (tonumber ms) 1000))))\n","language":"lisp","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(fn sleep [ms]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (os.execute (.. "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"sleep \""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"/"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (tonumber ms) "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"1000"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"))))\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"As another example, here is the output for my "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"caffeine"}]},{"type":"text","value":" toggle:"}]},{"type":"element","tag":"pre","props":{"className":"language-lua shiki shiki-themes github-light","code":"hs.hotkey.bind(HYPER, \"0\", function()\n hs.caffeinate.toggle(\"displayIdle\")\n if hs.caffeinate.get(\"displayIdle\") then\n helpers:show(\"Caffeine Enabled\", nil, helpers.styles.success, helpers.assets.check)\n else\n helpers:show(\"Caffeine Disabled\", nil, helpers.styles.error, helpers.assets.ban)\n end\nend)\n","language":"lua","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"hs."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"hotkey"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"bind"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(HYPER, "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"0\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"function"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"()\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" hs."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"caffeinate"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"toggle"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"displayIdle\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" if"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" hs."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"caffeinate"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"get"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"displayIdle\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"then\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" helpers"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":":"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"show"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Caffeine Enabled\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"nil"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", helpers."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"styles"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"success"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", helpers."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"assets"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"check"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" else\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" helpers"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":":"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"show"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Caffeine Disabled\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"nil"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", helpers."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"styles"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"error"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", helpers."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"assets"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"ban"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" end\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"end"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"className":"language-lisp shiki shiki-themes github-light","code":"(hs.hotkey.bind HYPER :0\n (fn [] (hs.caffeinate.toggle :displayIdle)\n (if (hs.caffeinate.get :displayIdle)\n (helpers:show \"Caffeine Enabled\" nil helpers.styles.success helpers.assets.check)\n (helpers:show \"Caffeine Disabled\" nil helpers.styles.error helpers.assets.ban)))) \n","language":"lisp","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(hs.hotkey.bind HYPER "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":":0\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (fn [] (hs.caffeinate.toggle "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":":displayIdle"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"if"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (hs.caffeinate.get "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":":displayIdle"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (helpers:show "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Caffeine Enabled\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" nil"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" helpers.styles.success helpers.assets.check)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (helpers:show "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Caffeine Disabled\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" nil"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" helpers.styles.error helpers.assets.ban))))\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This was especially helpful for more gnarly modules like the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"window"}]},{"type":"text","value":" module used for\nwindow management, and seeing the Lua and Fennel code side-by-side was a kick starter in\nlearning the language!"}]},{"type":"element","tag":"h2","props":{"id":"next-steps"},"children":[{"type":"text","value":"Next Steps"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"While my Fennel Hammerspoon configuration now works with parity to its Lua counterpart,\nI have not yet added new features or modules. I look forward to writing new Fennel code,\nand deepen my understanding of Lisp and the Fennel programming language."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Additionally, before beginning this endeavor, I was already aware of projects like\n"},{"type":"element","tag":"a","props":{"href":"https://github.com/agzam/spacehammer","rel":["nofollow"]},"children":[{"type":"text","value":"spacehammer"}]},{"type":"text","value":"; a wildly impressive Hammerspoon configuration written in Fennel, but,\nI wanted to start small and learn the integration myself. However, with the basics out\nof the way, I hope to explore this project further, and seek lessons-learned for the\nconfiguration of my own."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The full pull-request for translating my Lua Hammerspoon configuration to Fennel can be\nfound here: "},{"type":"element","tag":"a","props":{"href":"https://github.com/cmpadden/dotfiles/pull/19/files","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/cmpadden/dotfiles/pull/19/files"}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"initial-observations","depth":2,"text":"Initial Observations"},{"id":"integrating-fennel-with-hammerspoon","depth":2,"text":"Integrating Fennel with Hammerspoon"},{"id":"translating-lua-to-fennel","depth":2,"text":"Translating Lua to Fennel"},{"id":"next-steps","depth":2,"text":"Next Steps"}]}},"_type":"markdown","_id":"content:articles:fennel-initial-exploration.md","_source":"content","_file":"articles/fennel-initial-exploration.md","_extension":"md"},{"_path":"/articles/migrate-truenas-from-core-to-scale","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Migrate to TrueNAS Scale from TrueNAS Core","description":"TrueNAS Scale offers a variety of interesting features that are not supported in its TrueNAS Core counterpart. Most notably, because the base operating system is Debian Linux, opposed to FreeBSD, there is native support for Linux containers via Docker, and Kubernetes Pods! This post walks through the steps required to upgrade from TrueNAS Core to TrueNAS Scale.","date":"2021-12-28","tags":["homelab","supermicro","truenas"],"categories":["homelab"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"TrueNAS Scale offers a variety of interesting features that are not supported in its TrueNAS Core counterpart. Most notably, because the base operating system is Debian Linux, opposed to FreeBSD, there is native support for Linux containers via Docker, and Kubernetes Pods! This post walks through the steps required to upgrade from TrueNAS Core to TrueNAS Scale."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"TrueNAS Scale offers a variety of interesting features that are not supported in its TrueNAS Core counterpart. Most notably, because the base operating system is Debian Linux, opposed to FreeBSD, there is native support for Linux containers via Docker, and Kubernetes Pods! This post walks through the steps required to upgrade from TrueNAS Core to TrueNAS Scale."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Thankfully, the upgrade procedure to migrate from TrueNAS Core to TrueNAS Scale is relatively straight forward. All it requires is to create a bootable USB of the TrueNAS Scale image, boot the USB, and select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Install/Upgrade"}]},{"type":"text","value":" in the installation wizard. But for the sake of being thorough, you can find instructions on how to backup system configurations and install the OS below."}]},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Make a backup of your system’s configuration\n"},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Navigate to "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"System > General"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Click "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Save Config"}]},{"type":"text","value":", check the "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Export Secret Seed"}]},{"type":"text","value":" box, and click "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Save"}]}]}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Export dataset keys for the encrypted pools\n"},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Navigate to "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Storage > Pools"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Click the cog icon, and select "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Export Dataset Keys"}]}]}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Insert the TrueNAS Core bootable USB into the NAS"}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"From the Supermicro IPMI interface select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Remote Control"}]},{"type":"text","value":" and "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"iKVM/HTML5"}]},{"type":"text","value":" and select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Reboot"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Select the bootable USB as the boot device"}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"From the TrueNAS installation wizard, select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Install/Upgrade"}]},{"type":"text","value":", select the drive that contains the TrueNAS installation, and select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Upgrade Install"}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Reboot the device, and voila — you should be up-and-running! Give the system a quick rundown to validate that your settings and pools have transferred correctly, and then enjoy all the container goodness!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"For a breakdown of the differences between TrueNAS Core, Enterprise, and Scale, you can reference "},{"type":"element","tag":"a","props":{"href":"https://www.truenas.com/help-me-choose/","rel":["nofollow"]},"children":[{"type":"text","value":"this table"}]},{"type":"text","value":"."}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:migrate-truenas-from-core-to-scale.md","_source":"content","_file":"articles/migrate-truenas-from-core-to-scale.md","_extension":"md"},{"_path":"/articles/nuxt-content-rss-feed","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"How To Add an RSS Feed to a Nuxt Website","description":"If you are a user of Nuxt Content and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application.","draft":false,"date":"2024-01-06","tags":["nuxt","rss"],"categories":["programming"],"cover_image":"/images/nuxt-content-rss-feed.jpg","excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you are a user of "},{"type":"element","tag":"a","props":{"href":"https://content.nuxt.com/","rel":["nofollow"]},"children":[{"type":"text","value":"Nuxt Content"}]},{"type":"text","value":" and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you are a user of "},{"type":"element","tag":"a","props":{"href":"https://content.nuxt.com/","rel":["nofollow"]},"children":[{"type":"text","value":"Nuxt Content"}]},{"type":"text","value":" and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application."}]},{"type":"element","tag":"h2","props":{"id":"preface"},"children":[{"type":"text","value":"Preface"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In version 2 of Nuxt, the community module, "},{"type":"element","tag":"a","props":{"href":"https://github.com/nuxt-community/feed-module","rel":["nofollow"]},"children":[{"type":"text","value":"nuxt-community/feed-module"}]},{"type":"text","value":" was a popular choice for adding an RSS feed to your website. However, there has been an unresolved "},{"type":"element","tag":"a","props":{"href":"https://github.com/nuxt-community/feed-module/issues/106","rel":["nofollow"]},"children":[{"type":"text","value":"open issue"}]},{"type":"text","value":" since April 1st, 2022 to add support for Nuxt v3. Thankfully, implementing this feature without a module is relatively straight forward."}]},{"type":"element","tag":"h2","props":{"id":"instructions"},"children":[{"type":"text","value":"Instructions"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, install the "},{"type":"element","tag":"a","props":{"href":"https://www.npmjs.com/package/feed","rel":["nofollow"]},"children":[{"type":"text","value":"feed"}]},{"type":"text","value":" library into your project:"}]},{"type":"element","tag":"pre","props":{"className":"language-shell shiki shiki-themes github-light","code":"npm i -D feed\n","language":"shell","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"npm"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" i"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -D"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" feed\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, create a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"server/"}]},{"type":"text","value":" folder in your project if it does not already exist, and create a file named "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"server/routes/atom.ts"}]},{"type":"text","value":"."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Here, we will leverage the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"feed"}]},{"type":"text","value":" library and construct an XML representation of our Nuxt content. As you can see, we first define our "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"feed"}]},{"type":"text","value":" with metadata associated with our RSS feed. This will be used by RSS readers to provide context to the end user. Then, we query our Nuxt content with "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"serverQueryContent"}]},{"type":"text","value":" and append a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"feed.addItem"}]},{"type":"text","value":" for each article."}]},{"type":"element","tag":"pre","props":{"className":"language-ts shiki shiki-themes github-light","code":"import { serverQueryContent } from '#content/server';\nimport { Feed } from 'feed';\n\nconst BASE_URL = \"https://mywebsite.com\"\nconst AUTHOR_NAME = \"Firstname Lastname\"\n\nexport default defineEventHandler(async (event) => {\n\n const feed = new Feed({\n title: \"My Title\",\n description: \"My Description\",\n id: BASE_URL,\n link: BASE_URL,\n language: \"en\",\n image: `${BASE_URL}/images/placeholder.png`,\n favicon: `${BASE_URL}/favicon.ico`,\n copyright: `All rights reserved ${new Date().getFullYear()}, ${AUTHOR_NAME}`,\n updated: new Date(),\n generator: \"Nuxt static site generation + Feed for Node.js\",\n feedLinks: {\n atom: `${BASE_URL}/atom`\n },\n author: {\n name: AUTHOR_NAME,\n }\n });\n\n const articles = await serverQueryContent(event).find();\n\n articles.forEach((article) => {\n feed.addItem({\n title: article.title ? article.title : \"Missing Title\",\n id: article._path,\n link: `${BASE_URL}${article._path}`,\n description: article.description,\n author: [\n {\n name: AUTHOR_NAME,\n },\n ],\n date: new Date(article.date),\n image: article.cover_image ? `${BASE_URL}/${article.cover_image}` : undefined\n });\n });\n\n return feed.atom1();\n});\n","language":"ts","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" { serverQueryContent } "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" '#content/server'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":";\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" { Feed } "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 'feed'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":";\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"https://mywebsite.com\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" AUTHOR_NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"Firstname Lastname\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"export"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" default"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" defineEventHandler"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"async"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"event"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"=>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" feed"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" Feed"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" title: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"My Title\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" description: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"My Description\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":12},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" id: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":13},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" link: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":14},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" language: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"en\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":15},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" image: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}/images/placeholder.png`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":16},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" favicon: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}/favicon.ico`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":17},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" copyright: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`All rights reserved ${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" Date"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"()."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"getFullYear"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"()"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}, ${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"AUTHOR_NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":18},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" updated: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" Date"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(),\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":19},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" generator: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Nuxt static site generation + Feed for Node.js\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":20},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" feedLinks: {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":21},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" atom: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}/atom`\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":22},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" },\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":23},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" author: {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":24},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" name: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"AUTHOR_NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":25},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" }\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":26},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":27},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":28},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" articles"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" await"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" serverQueryContent"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(event)."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"find"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"();\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":29},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":30},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" articles."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"forEach"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"article"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"=>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":31},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" feed."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"addItem"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":32},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" title: article.title "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"?"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" article.title "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":":"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"Missing Title\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":33},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" id: article._path,\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":34},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" link: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"article"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"_path"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":35},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" description: article.description,\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":36},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" author: [\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":37},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":38},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" name: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"AUTHOR_NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":39},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" },\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":40},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ],\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":41},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" date: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" Date"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(article.date),\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":42},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" image: article.cover_image "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"?"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" `${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}/${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"article"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"cover_image"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" :"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" undefined\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":43},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":44},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":45},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":46},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" return"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" feed."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"atom1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"();\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":47},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"});\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And that's just about it! Except, if you are statically generating your website with the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"nuxt generate"}]},{"type":"text","value":" command, you will need to configure this server-side route to be pre-rendered on site generation. This is as simple as adding a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"nitro"}]},{"type":"text","value":" "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"prerender"}]},{"type":"text","value":" definition in your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"nuxt.config.ts"}]},{"type":"text","value":" file, like so:"}]},{"type":"element","tag":"pre","props":{"className":"language-ts shiki shiki-themes github-light","code":"nitro: {\n prerender: {\n routes: ['/atom']\n }\n}\n","language":"ts","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"nitro"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" prerender"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" routes"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": ["}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/atom'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" }\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"}\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"bonus"},"children":[{"type":"text","value":"Bonus"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"You may also be interested in adding a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sitemap.xml"}]},{"type":"text","value":" to your website. This can be done in almost an identical fashion!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Install the dependency:"}]},{"type":"element","tag":"pre","props":{"className":"language-shell shiki shiki-themes github-light","code":"npm i -D sitemap\n","language":"shell","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"npm"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" i"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -D"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" sitemap\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Create a route at "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"server/routes/sitemap.xml.ts"}]},{"type":"text","value":":"}]},{"type":"element","tag":"pre","props":{"className":"language-ts shiki shiki-themes github-light","code":"import { serverQueryContent } from '#content/server';\nimport { SitemapStream, streamToPromise } from 'sitemap';\n\nexport default defineEventHandler(async (event) => {\n const articles = await serverQueryContent(event).find();\n\n const sitemap = new SitemapStream({ hostname: 'https://my-website.com/' });\n\n // Add non nuxt content endpoints here\n sitemap.write({ url: '/' });\n sitemap.write({ url: '/articles' });\n\n // Dynamically generate routes for Nuxt markdown content\n articles.forEach((article) => sitemap.write({ url: article._path, changefreq: 'monthly' }));\n sitemap.end();\n\n return (await streamToPromise(sitemap));\n});\n","language":"ts","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" { serverQueryContent } "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" '#content/server'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":";\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" { SitemapStream, streamToPromise } "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 'sitemap'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":";\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"export"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" default"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" defineEventHandler"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"async"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"event"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"=>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" articles"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" await"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" serverQueryContent"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(event)."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"find"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"();\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" sitemap"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" SitemapStream"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({ hostname: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'https://my-website.com/'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":" // Add non nuxt content endpoints here\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" sitemap."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"write"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({ url: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" sitemap."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"write"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({ url: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/articles'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":12},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":13},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":" // Dynamically generate routes for Nuxt markdown content\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":14},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" articles."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"forEach"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"article"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"=>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" sitemap."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"write"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({ url: article._path, changefreq: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'monthly'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" }));\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":15},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" sitemap."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"end"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"();\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":16},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":17},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" return"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"await"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" streamToPromise"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(sitemap));\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":18},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"});\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And add the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"prerender"}]},{"type":"text","value":" entry in your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"nuxt.config.ts"}]},{"type":"text","value":":"}]},{"type":"element","tag":"pre","props":{"className":"language-ts shiki shiki-themes github-light","code":"nitro: {\n prerender: {\n routes: ['/sitemap.xml', '/atom']\n }\n}\n","language":"ts","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"nitro"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" prerender"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" routes"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": ["}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/sitemap.xml'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/atom'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" }\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"}\n"}]}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"preface","depth":2,"text":"Preface"},{"id":"instructions","depth":2,"text":"Instructions"},{"id":"bonus","depth":2,"text":"Bonus"}]}},"_type":"markdown","_id":"content:articles:nuxt-content-rss-feed.md","_source":"content","_file":"articles/nuxt-content-rss-feed.md","_extension":"md"},{"_path":"/articles/nuxt-v3-migration","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"This Website Has Been Migrated to Nuxt 3 🎉","description":"This website has been migrated to the latest version of the Nuxt web framework, and with it comes all of the exciting goodies that the Vue and Nuxt teams have been concocting over the past few years.\nNot to mention, all of the great plugins in the Vue ecosystem!","date":"2022-12-31","tags":["nuxt"],"categories":["web"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This website has been migrated to the latest version of the Nuxt web framework, and with it comes all of the exciting goodies that the Vue and Nuxt teams have been concocting over the past few years.\nNot to mention, all of the great plugins in the Vue ecosystem!"}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This website has been migrated to the latest version of the Nuxt web framework, and with it comes all of the exciting goodies that the Vue and Nuxt teams have been concocting over the past few years.\nNot to mention, all of the great plugins in the Vue ecosystem!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you're curious what changes were required to make the migration, you can check out "},{"type":"element","tag":"a","props":{"href":"https://github.com/cmpadden/cmpadden.github.io/pull/3","rel":["nofollow"]},"children":[{"type":"text","value":"pull request #3"}]},{"type":"text","value":" in the GitHub repository."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"img","props":{"alt":"Screenshot of Nuxt Migration Pull Request","src":"/images/nuxt-migration-pr.png"},"children":[]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"While the documentation for making this migration is great, there were many breaking changes, and the overall process was quite tedious.\nFor this reason, I opted to generate a new project entirely, and port existing code to this clean slate.\nI believe that this resulted in a project with a bit less cruft."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The most valuable resources for making these changes include:"}]},{"type":"element","tag":"ul","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://nuxt.com/docs/migration/overview","rel":["nofollow"]},"children":[{"type":"text","value":"The Nuxt Migration Guide"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://nuxt.com/docs/getting-started/introduction","rel":["nofollow"]},"children":[{"type":"text","value":"The Nuxt Framework Guide"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://tailwindcss.nuxt.dev/","rel":["nofollow"]},"children":[{"type":"text","value":"Nuxt Tailwind Module Documentation"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://content.nuxtjs.org/","rel":["nofollow"]},"children":[{"type":"text","value":"Nuxt Content Module Documentation"}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Part of the delay for doing this upgrade was in waiting for module developers to support this major release.\nI'm super thankful for all of the hard work they've don, and I'm excited to explore all of the new features available!\nI just hope that the breaking changes in this release don't cause too much fracturing of the community, as it does feel like déjà vu of Python 2 and 3."}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:nuxt-v3-migration.md","_source":"content","_file":"articles/nuxt-v3-migration.md","_extension":"md"},{"_path":"/articles/persistent-archlinux-usb","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Create a Persistent Arch Linux Bootable USB with Vagrant","description":"When installing a linux distribution, it is common for the instructions to have\nthe user create a bootable USB, boot from the device, and proceed with the\ninstallation procedure from that live medium. However, this blog post will\noutline an alternative approach where a virtual machine created with Vagrant\nwill be used in favor of the live medium.","date":"2020-01-09","draft":false,"tags":["vagrant","archlinux"],"categories":["linux"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"When installing a linux distribution, it is common for the instructions to have\nthe user create a bootable USB, boot from the device, and proceed with the\ninstallation procedure from that live medium. However, this blog post will\noutline an alternative approach where a virtual machine created with Vagrant\nwill be used in favor of the live medium."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"When installing a linux distribution, it is common for the instructions to have\nthe user create a bootable USB, boot from the device, and proceed with the\ninstallation procedure from that live medium. However, this blog post will\noutline an alternative approach where a virtual machine created with Vagrant\nwill be used in favor of the live medium."}]},{"type":"element","tag":"h1","props":{"id":"preface"},"children":[{"type":"text","value":"Preface"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The original intention was to use Docker for this process -- leveraging the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--device"}]},{"type":"text","value":" flag and mounting the target USB device in the Docker container,\nbut the underlying hypervisor in Docker Desktop for Mac does not support this.\n"},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.docker.com/docker-for-mac/docker-toolbox/","rel":["nofollow"]},"children":[{"type":"text","value":"1"}]},{"type":"text","value":" "},{"type":"element","tag":"a","props":{"href":"https://github.com/moby/hyperkit","rel":["nofollow"]},"children":[{"type":"text","value":"2"}]},{"type":"text","value":" "},{"type":"element","tag":"a","props":{"href":"https://github.com/docker/for-mac/issues/900","rel":["nofollow"]},"children":[{"type":"text","value":"3"}]}]},{"type":"text","value":" While there are workarounds using Docker\nMachine, Vagrant felt like the path of least resistance."}]},{"type":"element","tag":"h1","props":{"id":"instructions"},"children":[{"type":"text","value":"Instructions"}]},{"type":"element","tag":"h2","props":{"id":"create-an-arch-linux-virtual-machine-with-vagrant"},"children":[{"type":"text","value":"Create an Arch Linux Virtual Machine with Vagrant"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Get the latest Arch Linux image "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://app.vagrantup.com/archlinux/boxes/archlinux","rel":["nofollow"]},"children":[{"type":"text","value":"4"}]}]},{"type":"text","value":" from the Vagrant Cloud Box\nCatalog."}]},{"type":"element","tag":"pre","props":{"code":"vagrant box add archlinux/archlinux\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"vagrant"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" box"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" add"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" archlinux/archlinux\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Determine the USB vendor information for the thumb-drive that we will\npass-through to the virtual machine. Using the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"VBoxManage"}]},{"type":"text","value":" utility that comes\nwith Virtual Box, list the devices, and make note of the Vendor and Product ID."}]},{"type":"element","tag":"pre","props":{"code":" VBoxManage list usbhost\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" VBoxManage"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" usbhost\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Create a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Vagrantfile"}]},{"type":"text","value":" with "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"archlinx/archlinux"}]},{"type":"text","value":" as the target box, and the USB\ndevice information that is passed through. "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://antonyjepson.wordpress.com/2012/01/26/quickly-attaching-usb-devices-to-virtualbox-guests-using-vboxmanage/","rel":["nofollow"]},"children":[{"type":"text","value":"5"}]},{"type":"text","value":" "},{"type":"element","tag":"a","props":{"href":"https://gist.github.com/dscape/7d829c0c116ef419f963","rel":["nofollow"]},"children":[{"type":"text","value":"6"}]}]},{"type":"text","value":" Vagrant\noffers a handy customization parameter "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"vb.customize"}]},{"type":"text","value":" that calls the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"VBoxManage"}]},{"type":"text","value":" command under-the-hood, allowing one to enable the guest machine\nto access the host machine's USB devices."}]},{"type":"element","tag":"pre","props":{"code":"# -*- mode: ruby -*-\n# vi: set ft=ruby :\n\nVagrant.configure(\"2\") do |config|\n config.vm.box = \"archlinux/archlinux\"\n config.vm.provider \"virtualbox\" do |vb|\n vb.name = \"archlinux\"\n vb.customize ['modifyvm', :id, '--usb', 'on']\n vb.customize ['usbfilter', 'add', '1', '--target', :id, '--name', 'SanDisk Ultra Fit', '--vendorid', '0x0781', '--productid', '0x5583']\n end\nend\n","language":"txt","meta":"","className":"language-txt shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"# -*- mode: ruby -*-\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"# vi: set ft=ruby :\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Vagrant.configure(\"2\") do |config|\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" config.vm.box = \"archlinux/archlinux\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" config.vm.provider \"virtualbox\" do |vb|\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" vb.name = \"archlinux\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" vb.customize ['modifyvm', :id, '--usb', 'on']\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" vb.customize ['usbfilter', 'add', '1', '--target', :id, '--name', 'SanDisk Ultra Fit', '--vendorid', '0x0781', '--productid', '0x5583']\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" end\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"end\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"When virtual machine is brought up, the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"usbfilter"}]},{"type":"text","value":" is applied, and the guest\nis able to access to the host machine's USB device that was specified in the\nfilter."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Start the machine, "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ssh"}]},{"type":"text","value":" into the guest, and list the devices to confirm that\nthe USB device is available (see: "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"/dev/sdb"}]},{"type":"text","value":")."}]},{"type":"element","tag":"pre","props":{"code":"$ vagrant up\n$ vagrant ssh\n[vagrant@archlinux ~]$ lsblk\nNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT\nsda 8:0 0 20G 0 disk\n├─sda1 8:1 0 1.9G 0 part [SWAP]\n└─sda2 8:2 0 18.1G 0 part /\nsdb 8:16 1 28.7G 0 disk\n└─sdb1 8:17 1 8G 0 part\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" vagrant"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" up\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" vagrant"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ssh\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[vagrant@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]$ lsblk\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" MAJ:MIN"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" RM"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" SIZE"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" RO"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" TYPE"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" MOUNTPOINT\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sda"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 20G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" disk\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"├─sda1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 1.9G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" part"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" [SWAP]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"└─sda2"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:2"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 18.1G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" part"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" /\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sdb"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:16"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 28.7G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" disk\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"└─sdb1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:17"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" part\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"install-arch-linux-on-the-usb-drive"},"children":[{"type":"text","value":"Install Arch Linux on the USB Drive"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The "},{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/Installation_guide","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Installation Guide"}]},{"type":"text","value":" outlines the installation procedure in\ngreat detail -- the following steps follow this closely with a few alteration\ndue to installing onto removable media."}]},{"type":"element","tag":"h3","props":{"id":"partition-the-disk-uefi-with-gpt"},"children":[{"type":"text","value":"Partition the Disk (UEFI with GPT)"}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# fdisk /dev/sdb\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# fdisk /dev/sdb\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"code":"Command (m for help): p\nDisk /dev/sdb: 28.66 GiB, 30752636928 bytes, 60063744 sectors\nDisk model: Ultra Fit\nUnits: sectors of 1 * 512 = 512 bytes\nSector size (logical/physical): 512 bytes / 512 bytes\nI/O size (minimum/optimal): 512 bytes / 512 bytes\nDisklabel type: gpt\nDisk identifier: E1D6C445-1B79-AB4D-A442-FA4AD6DF4ECC\n\nDevice Start End Sectors Size Type\n/dev/sdb1 2048 1050623 1048576 512M EFI System\n/dev/sdb2 1050624 60063710 59013087 28.1G Linux filesystem\n\nFilesystem/RAID signature on partition 1 will be wiped.\n","language":"txt","meta":"","className":"language-txt shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Command (m for help): p\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Disk /dev/sdb: 28.66 GiB, 30752636928 bytes, 60063744 sectors\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Disk model: Ultra Fit\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Units: sectors of 1 * 512 = 512 bytes\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Sector size (logical/physical): 512 bytes / 512 bytes\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"I/O size (minimum/optimal): 512 bytes / 512 bytes\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Disklabel type: gpt\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Disk identifier: E1D6C445-1B79-AB4D-A442-FA4AD6DF4ECC\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Device Start End Sectors Size Type\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"/dev/sdb1 2048 1050623 1048576 512M EFI System\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":12},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"/dev/sdb2 1050624 60063710 59013087 28.1G Linux filesystem\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":13},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":14},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Filesystem/RAID signature on partition 1 will be wiped.\n"}]}]}]}]},{"type":"element","tag":"h3","props":{"id":"format-the-partitions"},"children":[{"type":"text","value":"Format the Partitions"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The UEFI specification mandates support for FAT file-systems, and FAT32 is\nrecommended for removable media. "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/EFI_system_partition#Format_the_partition","rel":["nofollow"]},"children":[{"type":"text","value":"7"}]}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# pacman -Sy dosfstools\n[root@archlinux ~]# mkfs.fat -F32 /dev/sdb1\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# pacman -Sy dosfstools\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mkfs.fat -F32 /dev/sdb1\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"As for the root partition, it is recommended to use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ext4"}]},{"type":"text","value":" without a journal to\nreduce the reads and writes to the file-system as this is detrimental to the\nflash-based USB drive. "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/Install_Arch_Linux_on_a_USB_key#Installation_tweaks","rel":["nofollow"]},"children":[{"type":"text","value":"8"}]}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# mkfs.ext4 -O \"^has_journal\" /dev/sdb2\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mkfs.ext4 -O "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"^has_journal\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" /dev/sdb2\n"}]}]}]}]},{"type":"element","tag":"h3","props":{"id":"mount-the-partitions-and-bootstrap-the-environment"},"children":[{"type":"text","value":"Mount the Partitions and Bootstrap the Environment"}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# mount /dev/sdb2 /mnt\n[root@archlinux ~]# mkdir -p /mnt/boot/efi\n[root@archlinux ~]# mount /dev/sdb1 /mnt/boot/efi\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mount /dev/sdb2 /mnt\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mkdir -p /mnt/boot/efi\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mount /dev/sdb1 /mnt/boot/efi\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# pacman -S arch-install-scripts\n[root@archlinux ~]# pacstrap /mnt base linux linux-firmware\n[root@archlinux ~]# genfstab -U /mnt >> /mnt/etc/fstab\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# pacman -S arch-install-scripts\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# pacstrap /mnt base linux linux-firmware\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# genfstab -U /mnt "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":">>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" /mnt/etc/fstab\n"}]}]}]}]},{"type":"element","tag":"h3","props":{"id":"configure-the-new-environment"},"children":[{"type":"text","value":"Configure the New Environment"}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# arch-chroot /mnt\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"[root@archlinux ~]# arch-chroot /mnt\n"}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux /]# ln -sf /usr/share/zoneinfo/US/Eastern /etc/localtime\n[root@archlinux /]# hwclock --systohc\n[root@archlinux /]# sed -i 's/#en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen\n[root@archlinux /]# locale-gen\n[root@archlinux /]# echo \"LANG=en_US.UTF-8\" > /etc/locale.conf\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"[root@archlinux /]# ln -sf /usr/share/zoneinfo/US/Eastern /etc/localtime\n[root@archlinux /]# hwclock --systohc\n[root@archlinux /]# sed -i 's/#en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen\n[root@archlinux /]# locale-gen\n[root@archlinux /]# echo \"LANG=en_US.UTF-8\" > /etc/locale.conf\n"}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux /]# hostnamectl set-hostname usb\n[root@archlinux /]# echo \"127.0.0.1 localhost\" >> /etc/hosts\n[root@archlinux /]# echo \"::1 localhost\" >> /etc/hosts\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"[root@archlinux /]# hostnamectl set-hostname usb\n[root@archlinux /]# echo \"127.0.0.1 localhost\" >> /etc/hosts\n[root@archlinux /]# echo \"::1 localhost\" >> /etc/hosts\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Note, one difference here from a standard installation is that the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--removable"}]},{"type":"text","value":" flag is specified when installing the GRUB bootloader.\n"},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/GRUB#UEFI_systems","rel":["nofollow"]},"children":[{"type":"text","value":"10"}]}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux /]# pacman -S grub\n[root@archlinux /]# grub-install --target=x86_64-efi --efi-directory=/boot/efi --removable --recheck\n[root@usb /]# grub-mkconfig -o /boot/grub/grub.cfg\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"[root@archlinux /]# pacman -S grub\n[root@archlinux /]# grub-install --target=x86_64-efi --efi-directory=/boot/efi --removable --recheck\n[root@usb /]# grub-mkconfig -o /boot/grub/grub.cfg\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Shutdown the virtual machine, restart the host machine, and boot the newly\ncreated Arch Linux thumb-drive!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"🎉"}]},{"type":"element","tag":"h2","props":{"id":"side-note"},"children":[{"type":"text","value":"Side-note"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"It was attempted to use the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"controlvm usbattach"}]},{"type":"text","value":" command to pass the USB\ndevice to the guest machine, but this did not work as it expects the virtual\nmachine to already be running, and the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"vb.customize"}]},{"type":"text","value":" option runs prior to\nbooting the machine. "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://www.vagrantup.com/docs/virtualbox/configuration.html#vboxmanage-customizations","rel":["nofollow"]},"children":[{"type":"text","value":"11"}]}]}]},{"type":"element","tag":"pre","props":{"code":"Command: [\"controlvm\", \"060a716b-1965-49e2-bc56-12beed5df716\", \"usbattach36fc9e60-c465-11cf-8056-444553540000\"]\n\nStderr: VBoxManage.exe: error: Machine '060a716b-1965-49e2-bc56-12beed5df716' is not currently running.\n","language":"txt","meta":"","className":"language-txt shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Command: [\"controlvm\", \"060a716b-1965-49e2-bc56-12beed5df716\", \"usbattach36fc9e60-c465-11cf-8056-444553540000\"]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Stderr: VBoxManage.exe: error: Machine '060a716b-1965-49e2-bc56-12beed5df716' is not currently running.\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"references"},"children":[{"type":"text","value":"References"}]},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.docker.com/docker-for-mac/docker-toolbox/","rel":["nofollow"]},"children":[{"type":"text","value":"Docker Desktop on Mac vs. Docker Toolbox"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/moby/hyperkit","rel":["nofollow"]},"children":[{"type":"text","value":"GitHub - HyperKit"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/docker/for-mac/issues/900","rel":["nofollow"]},"children":[{"type":"text","value":"GitHub - Docker for Mac - Issue #900"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://app.vagrantup.com/archlinux/boxes/archlinux","rel":["nofollow"]},"children":[{"type":"text","value":"Vagrant Cloud - Arch Linux"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://antonyjepson.wordpress.com/2012/01/26/quickly-attaching-usb-devices-to-virtualbox-guests-using-vboxmanage/","rel":["nofollow"]},"children":[{"type":"text","value":"Attaching USB Devices to VirtualBox Guests using VBoxManage"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://gist.github.com/dscape/7d829c0c116ef419f963","rel":["nofollow"]},"children":[{"type":"text","value":"GitHub Gist - Vagrant USB Filter"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/EFI_system_partition#Format_the_partition","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Wiki - EFI System Partition - Format Partitions"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/Install_Arch_Linux_on_a_USB_key#Installation_tweaks","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Wiki - Arch Linux on USB - Installation Tweaks"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/Installation_guide","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Wiki - Installation Guide"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/GRUB#UEFI_systems","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Wiki - GRUB - UEFI Systems"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://www.vagrantup.com/docs/virtualbox/configuration.html#vboxmanage-customizations","rel":["nofollow"]},"children":[{"type":"text","value":"Vagrant VBoxManage Customizations "}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"create-an-arch-linux-virtual-machine-with-vagrant","depth":2,"text":"Create an Arch Linux Virtual Machine with Vagrant"},{"id":"install-arch-linux-on-the-usb-drive","depth":2,"text":"Install Arch Linux on the USB Drive","children":[{"id":"partition-the-disk-uefi-with-gpt","depth":3,"text":"Partition the Disk (UEFI with GPT)"},{"id":"format-the-partitions","depth":3,"text":"Format the Partitions"},{"id":"mount-the-partitions-and-bootstrap-the-environment","depth":3,"text":"Mount the Partitions and Bootstrap the Environment"},{"id":"configure-the-new-environment","depth":3,"text":"Configure the New Environment"}]},{"id":"side-note","depth":2,"text":"Side-note"},{"id":"references","depth":2,"text":"References"}]}},"_type":"markdown","_id":"content:articles:persistent-archlinux-usb.md","_source":"content","_file":"articles/persistent-archlinux-usb.md","_extension":"md"},{"_path":"/articles/podcast-transcription-whispercpp","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Easily Transcribe Podcasts with Whisper.cpp","description":"If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive whisper.cpp project. This high-performance fork of OpenAI's Whisper can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the Alter Everything podcast.","draft":false,"date":"2024-01-08","tags":["whisper.cpp","ml"],"categories":["programming"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive "},{"type":"element","tag":"a","props":{"href":"https://github.com/ggerganov/whisper.cpp","rel":["nofollow"]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" project. This high-performance fork of "},{"type":"element","tag":"a","props":{"href":"https://github.com/openai/whisper","rel":["nofollow"]},"children":[{"type":"text","value":"OpenAI's Whisper"}]},{"type":"text","value":" can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the "},{"type":"element","tag":"a","props":{"href":"https://podcasts.apple.com/us/podcast/alter-everything/id1356137854","rel":["nofollow"]},"children":[{"type":"text","value":"Alter Everything"}]},{"type":"text","value":" podcast."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive "},{"type":"element","tag":"a","props":{"href":"https://github.com/ggerganov/whisper.cpp","rel":["nofollow"]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" project. This high-performance fork of "},{"type":"element","tag":"a","props":{"href":"https://github.com/openai/whisper","rel":["nofollow"]},"children":[{"type":"text","value":"OpenAI's Whisper"}]},{"type":"text","value":" can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the "},{"type":"element","tag":"a","props":{"href":"https://podcasts.apple.com/us/podcast/alter-everything/id1356137854","rel":["nofollow"]},"children":[{"type":"text","value":"Alter Everything"}]},{"type":"text","value":" podcast."}]},{"type":"element","tag":"h2","props":{"id":"obtain-audio-files"},"children":[{"type":"text","value":"Obtain Audio File(s)"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, let's get the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"wav"}]},{"type":"text","value":" file from YouTube using the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"youtube-dl"}]},{"type":"text","value":" utility. It should be noted that "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" expects "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"wav"}]},{"type":"text","value":" filetypes, and this utility defaults to "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"mp3"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"code":" $ youtube-dl \\\n --extract-audio \\\n --audio-format wav \\\n --output podcast.wav \\\n \"https://www.youtube.com/watch?v=CoUN690wSYQ\"\n","language":"sh","meta":"","className":"language-sh shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" youtube-dl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --extract-audio"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --audio-format"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" wav"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --output"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast.wav"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"https://www.youtube.com/watch?v=CoUN690wSYQ\"\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This file has a 44.1 kHz sample rate, and "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" expects 16 kHz, so let's go ahead and convert that."}]},{"type":"element","tag":"pre","props":{"code":" $ file podcast.wav\npodcast.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz\n\n $ ffmpeg -i podcast.wav -ar 16000 podcast-16khz.wav\n\n $ file podcast-16khz.wav\npodcast-16khz.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 16000 Hz\n\n# NOTE: it looks like it's possible to specify this conversion as a post-process as a\n# flag to the `youtube-dl` command -- I will explore this further next time...\n# youtube-dl --extract-audio --audio-quality 0 --audio-format mp3 --postprocessor-args \"-ar 44100\" %dl%\n","language":"sh","meta":"","className":"language-sh shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" file"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast.wav\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"podcast.wav:"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" RIFF"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ffmpeg"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -i"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast.wav"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -ar"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 16000"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast-16khz.wav\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" file"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast-16khz.wav\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"podcast-16khz.wav:"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" RIFF"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 16000 Hz\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# NOTE: it looks like it's possible to specify this conversion as a post-process as a\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# flag to the `youtube-dl` command -- I will explore this further next time...\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# youtube-dl --extract-audio --audio-quality 0 --audio-format mp3 --postprocessor-args \"-ar 44100\" %dl%\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"build-whispercpp-transcribe-audio"},"children":[{"type":"text","value":"Build "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" & Transcribe Audio"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, let's get the latest version of "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":", download the English Whisper model, and build the example."}]},{"type":"element","tag":"pre","props":{"code":"# Clone the `whisper.cpp` repository\n $ git clone --depth 1 git@github.com:ggerganov/whisper.cpp && cd whisper.cpp\n\n# Download the English Whisper model in `ggml` format\n $ bash ./models/download-ggml-model.sh base.en\n\n# Build the main example\n $ make\n","language":"sh","meta":"","className":"language-sh shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# Clone the `whisper.cpp` repository\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" git"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" clone"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --depth"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" git@github.com:ggerganov/whisper.cpp"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" && "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"cd"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" whisper.cpp\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# Download the English Whisper model in `ggml` format\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" bash"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ./models/download-ggml-model.sh"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" base.en\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# Build the main example\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" make\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And finally, let's transcribe that podcast!"}]},{"type":"element","tag":"pre","props":{"code":" $ ./main \\\n -m ~/workspace/whisper.cpp/models/ggml-base.en.bin \\\n -f ~/Downloads/podcast-16khz.wav \\\n --output-vtt \\\n --output-file out\n\n# whisper_print_timings: load time = 114.71 ms\n# whisper_print_timings: fallbacks = 0 p / 0 h\n# whisper_print_timings: mel time = 692.20 ms\n# whisper_print_timings: sample time = 22278.10 ms / 27893 runs ( 0.80 ms per run)\n# whisper_print_timings: encode time = 10000.75 ms / 55 runs ( 181.83 ms per run)\n# whisper_print_timings: decode time = 331.77 ms / 54 runs ( 6.14 ms per run)\n# whisper_print_timings: batchd time = 45236.73 ms / 27566 runs ( 1.64 ms per run)\n# whisper_print_timings: prompt time = 1921.90 ms / 11832 runs ( 0.16 ms per run)\n# whisper_print_timings: total time = 80709.54 ms\n","language":"sh","meta":"","className":"language-sh shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ./main"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -m"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ~/workspace/whisper.cpp/models/ggml-base.en.bin"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -f"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ~/Downloads/podcast-16khz.wav"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --output-vtt"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --output-file"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" out\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: load time = 114.71 ms\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: fallbacks = 0 p / 0 h\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: mel time = 692.20 ms\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: sample time = 22278.10 ms / 27893 runs ( 0.80 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: encode time = 10000.75 ms / 55 runs ( 181.83 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":12},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: decode time = 331.77 ms / 54 runs ( 6.14 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":13},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: batchd time = 45236.73 ms / 27566 runs ( 1.64 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":14},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: prompt time = 1921.90 ms / 11832 runs ( 0.16 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":15},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: total time = 80709.54 ms\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"A full podcast transcribed in ~80 seconds on an M1 Mac Mini -- not too bad!"}]},{"type":"element","tag":"pre","props":{"code":"# out.vtt\n\n00:00:00.000 --> 00:00:06.480\n >> Hi everyone. We recently launched a short engagement feedback survey for the Alter Everything\n\n00:00:06.480 --> 00:00:11.360\n podcast. Click the link in the episode description wherever you're listening to let us know what\n\n00:00:11.360 --> 00:00:16.320\n you think and help us improve our show.\n\n00:00:16.320 --> 00:00:21.200\n Welcome to Alter Everything, a podcast about data science and analytics culture. I'm Megan\n\n00:00:21.200 --> 00:00:26.440\n Dibble and today I'm talking with Nick Schrock, CTO and founder of Dagster Labs. We discussed\n\n00:00:26.440 --> 00:00:31.560\n data engineering trends, challenges in the field, why he started his company, and what\n\n00:00:31.560 --> 00:00:38.960\n makes him excited about the future of data engineering. Let's get started.\n\n00:00:38.960 --> 00:00:42.720\n >> Hi, Nick. It's great to have you on our show today. Thanks for being here.\n\n00:00:42.720 --> 00:00:43.920\n >> Thanks for having me.\n\n00:00:43.920 --> 00:00:48.280\n >> Yeah. Could you start off by giving an introduction to yourself for our listeners?\n\n00:00:48.280 --> 00:00:52.920\n >> Sure. My name is Nick Schrock. I'm the CTO and founder of Dagster Labs. There's the\n\n00:00:52.920 --> 00:00:59.520\n company behind Dagster, which is a data orchestration framework. Prior to doing this, I was an engineer\n\n00:00:59.520 --> 00:01:05.960\n at Facebook from 2009, 2017. While I was there, I found a team called product infrastructure\n\n00:01:05.960 --> 00:01:09.800\n whose goal was to make our application developers more efficient and productive, and a bunch\n\n00:01:09.800 --> 00:01:13.840\n of open source work came out of that actually, one of which was React, which I had nothing\n\n00:01:13.840 --> 00:01:18.040\n to do with, but actually the CEO of Dagster Labs co-created and I personally co-created\n\n00:01:18.040 --> 00:01:22.640\n GraphQL. So as I like to say, Pete and I were present at the creation of the full hipster\n\n00:01:22.640 --> 00:01:28.680\n stack. I moved on to Facebook in 2017, figuring out what to do next, and this data engineering\n\n00:01:28.680 --> 00:01:32.960\n and data orchestration problem really got me hooked actually quite soon after I left,\n\n00:01:32.960 --> 00:01:36.280\n and the rest is history. I'm sure we'll get into that more.\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"# out.vtt\n\n00:00:00.000 --> 00:00:06.480\n >> Hi everyone. We recently launched a short engagement feedback survey for the Alter Everything\n\n00:00:06.480 --> 00:00:11.360\n podcast. Click the link in the episode description wherever you're listening to let us know what\n\n00:00:11.360 --> 00:00:16.320\n you think and help us improve our show.\n\n00:00:16.320 --> 00:00:21.200\n Welcome to Alter Everything, a podcast about data science and analytics culture. I'm Megan\n\n00:00:21.200 --> 00:00:26.440\n Dibble and today I'm talking with Nick Schrock, CTO and founder of Dagster Labs. We discussed\n\n00:00:26.440 --> 00:00:31.560\n data engineering trends, challenges in the field, why he started his company, and what\n\n00:00:31.560 --> 00:00:38.960\n makes him excited about the future of data engineering. Let's get started.\n\n00:00:38.960 --> 00:00:42.720\n >> Hi, Nick. It's great to have you on our show today. Thanks for being here.\n\n00:00:42.720 --> 00:00:43.920\n >> Thanks for having me.\n\n00:00:43.920 --> 00:00:48.280\n >> Yeah. Could you start off by giving an introduction to yourself for our listeners?\n\n00:00:48.280 --> 00:00:52.920\n >> Sure. My name is Nick Schrock. I'm the CTO and founder of Dagster Labs. There's the\n\n00:00:52.920 --> 00:00:59.520\n company behind Dagster, which is a data orchestration framework. Prior to doing this, I was an engineer\n\n00:00:59.520 --> 00:01:05.960\n at Facebook from 2009, 2017. While I was there, I found a team called product infrastructure\n\n00:01:05.960 --> 00:01:09.800\n whose goal was to make our application developers more efficient and productive, and a bunch\n\n00:01:09.800 --> 00:01:13.840\n of open source work came out of that actually, one of which was React, which I had nothing\n\n00:01:13.840 --> 00:01:18.040\n to do with, but actually the CEO of Dagster Labs co-created and I personally co-created\n\n00:01:18.040 --> 00:01:22.640\n GraphQL. So as I like to say, Pete and I were present at the creation of the full hipster\n\n00:01:22.640 --> 00:01:28.680\n stack. I moved on to Facebook in 2017, figuring out what to do next, and this data engineering\n\n00:01:28.680 --> 00:01:32.960\n and data orchestration problem really got me hooked actually quite soon after I left,\n\n00:01:32.960 --> 00:01:36.280\n and the rest is history. I'm sure we'll get into that more.\n"}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"obtain-audio-files","depth":2,"text":"Obtain Audio File(s)"},{"id":"build-whispercpp-transcribe-audio","depth":2,"text":"Build whisper.cpp & Transcribe Audio"}]}},"_type":"markdown","_id":"content:articles:podcast-transcription-whispercpp.md","_source":"content","_file":"articles/podcast-transcription-whispercpp.md","_extension":"md"},{"_path":"/articles/quick-tip-rerunning-bash-commands","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Tip: Re-running Bash Commands","description":"Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use sudo for a command that requires\nroot privileges.","date":"2021-09-22","draft":false,"tags":["tip","bash"],"categories":["tips"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sudo"}]},{"type":"text","value":" for a command that requires\nroot privileges."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sudo"}]},{"type":"text","value":" for a command that requires\nroot privileges."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ pacman -Syu\nerror: you cannot perform this operation unless you are root.\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pacman"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -Syu\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"error:"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" you"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" cannot"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" perform"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" this"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" operation"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" unless"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" you"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" are"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" root.\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Well, I have good news for you -- you can easily re-issue a command with the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!!"}]},{"type":"text","value":" designator! Simply type "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sudo"}]},{"type":"text","value":" followed by "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!!"}]},{"type":"text","value":" and you're good to go."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ sudo !!\nsudo pacman -Syu\n[sudo] password for colton:\n:: Synchronizing package databases...\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" !!\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pacman"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -Syu\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[sudo] password "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"for"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" colton:\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"::"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" Synchronizing"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" package"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" databases...\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"--"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Commands that are prefixed with a bang, "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!"}]},{"type":"text","value":", are considered "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Event\nDesignators,"}]},{"type":"text","value":" and are references to your command-line history. You can take a\nlook at your history with the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"history"}]},{"type":"text","value":" command."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ history\n 1021 touch hello_world.txt\n 1022 ls\n 1023 echo \"Here we go again!\"\n 1024 find . -name *.py\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" history\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" 1021"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" touch"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" hello_world.txt\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" 1022"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ls\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" 1023"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" echo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"Here we go again!\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" 1024"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" find"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -name"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" *"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":".py\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"There are many ways to use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!"}]},{"type":"text","value":" in your shell. For example, if you wanted to\nre-issue a specific command in your history, you could use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!n"}]},{"type":"text","value":" where "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"n"}]},{"type":"text","value":" is\nthe number next to the command in your history."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ !1023\necho \"Here we go again!\"\nHere we go again!\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" !1023\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"echo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"Here we go again!\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"Here"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" we"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" go"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" again!\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Or... if you wanted to run the command you issued 4-commands ago, you can use\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!-4"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ !-4\nls\nhello_world.txt\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" !-4\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"ls\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"hello_world.txt\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Or... if you wanted to run the last command that started with the string\n"},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"find"}]},{"type":"text","value":", you can use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!find"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ !find\nfind . -name *.py\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" !find\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"find"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -name"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" *"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":".py\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Be sure to check out the "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Event Designators"}]},{"type":"text","value":" section of the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"bash"}]},{"type":"text","value":" "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"man"}]},{"type":"text","value":" pages\nfor more information!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"--"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"As an aside, for even faster command-line history navigation, be sure to check\nout the excellent "},{"type":"element","tag":"a","props":{"href":"https://github.com/junegunn/fzf","rel":["nofollow"]},"children":[{"type":"text","value":"fzf"}]},{"type":"text","value":" utility by "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"junegunn."}]},{"type":"text","value":"\nOne of the many features of "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"fzf"}]},{"type":"text","value":" is browsing and re-issuing commands from your\ncommand-line history with a fuzzy-finder!"}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:quick-tip-rerunning-bash-commands.md","_source":"content","_file":"articles/quick-tip-rerunning-bash-commands.md","_extension":"md"},{"_path":"/articles/reset-ipmi-password-from-host-os","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Reset IPMI Credentials from the Host OS","description":"If you ever find yourself locked out of the Intelligent Platform Management Interface (IPMI) of a server, these\ninstructions will guide your through the process of resetting the credentials to their default values from the host\noperating system.","date":"2021-12-27","tags":["homelab","supermicro","truenas"],"categories":["homelab"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you ever find yourself locked out of the Intelligent Platform Management Interface (IPMI) of a server, these\ninstructions will guide your through the process of resetting the credentials to their default values from the host\noperating system."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you ever find yourself locked out of the Intelligent Platform Management Interface (IPMI) of a server, these\ninstructions will guide your through the process of resetting the credentials to their default values from the host\noperating system."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you are using an operating system like TrueNAS -- good news! It's possible to reset the IPMI password directly from\nthe web interface. This is done by navigating to "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Network > IPMI"}]},{"type":"text","value":", and simply entering a new value in the "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"IPMI\nPassword Reset"}]},{"type":"text","value":" field."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you are using some other OS that doesn't have this feature, you can achieve similar results by using the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ipmitool"}]},{"type":"text","value":"\ncommand-line utility."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, you'll want to determine the user ID associated with the user for whom you'd like to reset the password."}]},{"type":"element","tag":"pre","props":{"code":"# ipmitool user list\nID Name Callin Link Auth IPMI Msg Channel Priv Limit\n1 true false false Unknown (0x00)\n2 ADMIN true false false Unknown (0x00)\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"# ipmitool user list\nID Name Callin Link Auth IPMI Msg Channel Priv Limit\n1 true false false Unknown (0x00)\n2 ADMIN true false false Unknown (0x00)\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In this case, we will be resetting the password for "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"ADMIN"}]},{"type":"text","value":" who has a user ID of "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"2"}]},{"type":"text","value":". Then we'll assign the new\npassword like so:"}]},{"type":"element","tag":"pre","props":{"code":"# ipmitool user set password 2 \n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"# ipmitool user set password 2 \n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And you should be good to go!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"..."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Alternatively, if you'd like to factory reset the baseboard management controller (BMC), which will reset the IPMI\ncredentials to their default value, you can issue the following command."}]},{"type":"element","tag":"pre","props":{"code":"# ipmitool raw 0x3c 0x40\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"# ipmitool raw 0x3c 0x40\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Where "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"0x3c"}]},{"type":"text","value":" is the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":""}]},{"type":"text","value":" argument, a.k.a. the network function code that defines the functional routing for\nmessages, and "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"0x40"}]},{"type":"text","value":" is the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":""}]},{"type":"text","value":". According to section 5.1 of the "},{"type":"element","tag":"a","props":{"href":"https://www.intel.com/content/dam/www/public/us/en/documents/product-briefs/ipmi-second-gen-interface-spec-v2-rev1-1.pdf","rel":["nofollow"]},"children":[{"type":"text","value":"IPMI interface\nspecification"}]},{"type":"text","value":",\n"},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"netfn"}]},{"type":"text","value":" codes ranging from 0x30 to 0x3F are reserved for vendor specific functions. I searched around for some\nSupermicro references on these vendor specific network functions without much luck other than various "},{"type":"element","tag":"a","props":{"href":"https://www.supermicro.com/support/faqs/faq.cfm?faq=15448","rel":["nofollow"]},"children":[{"type":"text","value":"support\nresponses"}]},{"type":"text","value":" on how to reset a device. Bummer!"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:reset-ipmi-password-from-host-os.md","_source":"content","_file":"articles/reset-ipmi-password-from-host-os.md","_extension":"md"},{"_path":"/articles/ssh-ed25519-sk-yubikey","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Configuring a YubiKey for use with OpenSSH","description":"YubiKey's are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" ed25519-sk key type that supports FIDO compliant hardware keys.","draft":false,"date":"2024-06-09","tags":["unix","configurations"],"categories":["tooling","tips"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://www.yubico.com/","rel":["nofollow"]},"children":[{"type":"text","value":"YubiKey's"}]},{"type":"text","value":" are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ed25519-sk"}]},{"type":"text","value":" key type that supports FIDO compliant hardware keys."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://www.yubico.com/","rel":["nofollow"]},"children":[{"type":"text","value":"YubiKey's"}]},{"type":"text","value":" are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ed25519-sk"}]},{"type":"text","value":" key type that supports FIDO compliant hardware keys."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In "},{"type":"element","tag":"a","props":{"href":"https://www.openssh.com/txt/release-8.2","rel":["nofollow"]},"children":[{"type":"text","value":"release 8.2 of OpenSSH"}]},{"type":"text","value":" support for FIDO devices was added with public key types \"ecdsa-sk\" and \"ed25519-sk\" (-sk standing for \"security key\"). This key type is supported by YubiKey's with firmware version 5.2.3 or higher."}]},{"type":"element","tag":"blockquote","props":{},"children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This release adds support for FIDO/U2F hardware authenticators to OpenSSH. U2F/FIDO are open standards for inexpensive two-factor authentication hardware that are widely used for website authentication. In OpenSSH FIDO devices are supported by new public key types \"ecdsa-sk\" and \"ed25519-sk\", along with corresponding certificate types."}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Let's get started by installing the latest version of OpenSSH via "},{"type":"element","tag":"a","props":{"href":"https://brew.sh/","rel":["nofollow"]},"children":[{"type":"text","value":"Homebrew"}]},{"type":"text","value":", along with the YubiKey Manager (ykman) CLI. The version of OpenSSH included with macOS is not compatible."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"$ brew install openssh ykman\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" brew"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" openssh"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ykman\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, let's confirm that our YubiKey has a firmware that is greater than 5.2.3:"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"$ ykman list\nYubiKey 5Ci (5.4.3) [OTP+FIDO+CCID]\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ykman"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"YubiKey"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 5Ci"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (5.4.3) [OTP+FIDO+CCID]\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Next, we'll go ahead and enable a pin on our device via the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"change-pin"}]},{"type":"text","value":" command, as this a requirement for our use."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"$ ykman fido access change-pin\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ykman"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" fido"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" access"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" change-pin\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And last, we'll generate the key on our device!"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"$ ssh-keygen -t ed25519-sk -O resident\nGenerating public/private ed25519-sk key pair.\nYou may need to touch your authenticator to authorize key generation.\n...\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ssh-keygen"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -t"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ed25519-sk"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -O"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" resident\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"Generating"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" public/private"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ed25519-sk"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" key"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pair.\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"You"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" may"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" need"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" to"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" touch"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" your"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" authenticator"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" to"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" authorize"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" key"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" generation.\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"...\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"We specify "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"resident"}]},{"type":"text","value":" to indicate that the key handle is to be stored on the YubiKey itself, since we will be using this device with multiple computers."}]},{"type":"element","tag":"pre","props":{"className":"language-txt shiki shiki-themes github-light","code":"resident\n Indicate that the key handle should be stored on the FIDO\n authenticator itself. This makes it easier to use the\n authenticator on multiple computers. Resident keys may be\n supported on FIDO2 authenticators and typically require that a PIN\n be set on the authenticator prior to generation. Resident keys\n may be loaded off the authenticator using ssh-add(1). Storing\n both parts of a key on a FIDO authenticator increases the\n likelihood of an attacker being able to use a stolen authenticator\n device.\n","language":"txt","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"resident\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" Indicate that the key handle should be stored on the FIDO\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" authenticator itself. This makes it easier to use the\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" authenticator on multiple computers. Resident keys may be\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" supported on FIDO2 authenticators and typically require that a PIN\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" be set on the authenticator prior to generation. Resident keys\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" may be loaded off the authenticator using ssh-add(1). Storing\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" both parts of a key on a FIDO authenticator increases the\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" likelihood of an attacker being able to use a stolen authenticator\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" device.\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And that's all it takes -- simple enough. Now, when interacting with "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"ssh"}]},{"type":"text","value":" or "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"git"}]},{"type":"text","value":" you will be prompted to touch the YubiKey to bring that little bit of physical 2FA."}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:ssh-ed25519-sk-yubikey.md","_source":"content","_file":"articles/ssh-ed25519-sk-yubikey.md","_extension":"md"},{"_path":"/articles/unit-testing-micropython-with-mocks","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Unit Testing in MicroPython with Mocks","description":"Unit testing code for embedded systems can be challenging. While it's possible\nto leverage emulators, write side-effect free code, or run tests on the\nhardware itself, it's often easiest to unit test the code on your personal\ncomputer with mocked hardware functionality.","date":"2020-02-07","draft":false,"tags":["micropython","testing","mocks","tutorial"],"categories":["python","embedded"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Unit testing code for embedded systems can be challenging. While it's possible\nto leverage emulators, write side-effect free code, or run tests on the\nhardware itself, it's often easiest to unit test the code on your personal\ncomputer with mocked hardware functionality."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Unit testing code for embedded systems can be challenging. While it's possible\nto leverage emulators, write side-effect free code, or run tests on the\nhardware itself, it's often easiest to unit test the code on your personal\ncomputer with mocked hardware functionality."}]},{"type":"element","tag":"h1","props":{"id":"mocking"},"children":[{"type":"text","value":"Mocking"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Mocks allow us to replace the hardware interfacing functionality under-the-hood\nwith predefined results and side-effects. For example, if there is a piece of\nlogic that retrieves values from an accelerometer to get a device's\norientation, it would be possible to mock the returned values of the\naccelerometer -- allowing us to run the unit tests on a device that does not\nhave an accelerometer sensor installed."}]},{"type":"element","tag":"h1","props":{"id":"a-micropython-mocking-example"},"children":[{"type":"text","value":"A MicroPython Mocking Example"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In this example, we will be unit testing a module named "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"time_logger"}]},{"type":"text","value":", that\ndepends on the MicroPython library "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime"}]},{"type":"text","value":" to log the most recent Epoch time to\na file."}]},{"type":"element","tag":"pre","props":{"className":"language-python shiki shiki-themes github-light","code":"# time_logger.py\n\nclass TimeLogger(object):\n\n def save_time(self):\n \"\"\" Overwrite a file with the most recent Epoch timestamp from `utime`\n \"\"\"\n with open(\"LAST_KNOWN_TIME\", \"w+\") as f:\n f.write(str(utime.time()))\n","language":"python","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# time_logger.py\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"class"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" TimeLogger"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"object"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" def"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" save_time"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(self):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"\"\" Overwrite a file with the most recent Epoch timestamp from `utime`\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"\"\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" with"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" open"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"LAST_KNOWN_TIME\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"w+\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"as"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" f:\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" f.write("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"str"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(utime.time()))\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, because the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime"}]},{"type":"text","value":" module is not installed on the machine that the unit\ntests on, we must mock "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime"}]},{"type":"text","value":" module before importing "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"time_logger"}]},{"type":"text","value":" in our\nunit test file."}]},{"type":"element","tag":"pre","props":{"className":"language-python shiki shiki-themes github-light","code":"# test_time_logger.py\n\nimport unittest\n\nfrom unittest.mock import MagicMock\n\nsys.modules['utime'] = MagicMock()\nfrom time_logger import TimeLogger\n","language":"python","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# test_time_logger.py\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" unittest\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" unittest.mock "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" MagicMock\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"sys.modules["}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'utime'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"] "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" MagicMock()\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" time_logger "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" TimeLogger\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, we can write a test that patches the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime.time"}]},{"type":"text","value":" functionality so that\nit returns a value of our choosing -- in this case, "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"1234"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-python shiki shiki-themes github-light","code":"class TestTimeLogger(unittest.TestCase):\n\n def test_save_time(self):\n \"\"\" Verify that the Epoch time is written to file\n \"\"\"\n with unittest.mock.patch(\"utime.time\", return_value=1234):\n t = TimeLogger()\n t.save_time()\n with open(\"LAST_KNOWN_TIME\") as f:\n self.assertEqual(\"1234\", f.read())\n","language":"python","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"class"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" TestTimeLogger"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"unittest"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"TestCase"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" def"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" test_save_time"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(self):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"\"\" Verify that the Epoch time is written to file\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"\"\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" with"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" unittest.mock.patch("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"utime.time\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"return_value"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"1234"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" t "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" TimeLogger()\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" t.save_time()\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" with"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" open"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"LAST_KNOWN_TIME\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"as"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" f:\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" self"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":".assertEqual("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"1234\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", f.read())\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Now, when the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"save_time"}]},{"type":"text","value":" method gets the latest time from "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime.time()"}]},{"type":"text","value":", the\nvalue will be patched to return "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"1234"}]},{"type":"text","value":". That value will be written to a file,\nand our unit test will pass!"}]},{"type":"element","tag":"h2","props":{"id":"references"},"children":[{"type":"text","value":"References"}]},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.python.org/3/library/unittest.html","rel":["nofollow"]},"children":[{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"unittest"}]},{"type":"text","value":" — Unit testing framework"}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"references","depth":2,"text":"References"}]}},"_type":"markdown","_id":"content:articles:unit-testing-micropython-with-mocks.md","_source":"content","_file":"articles/unit-testing-micropython-with-mocks.md","_extension":"md"},{"_path":"/articles/vim-fugitive-gpg-pinentry","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Using pinentry-mac to sign commits from vim-fugitive","description":"In order to sign git commits from within Vim using a plugin like tpope/vim-fugitive, it is necessary to configure the gpg-agent to use a GUI based pinentry-program.","draft":false,"date":"2024-05-11","tags":["vim","tip"],"categories":["tooling","tips"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In order to sign git commits from within Vim using a plugin like "},{"type":"element","tag":"a","props":{"href":"https://github.com/tpope/vim-fugitive","rel":["nofollow"]},"children":[{"type":"text","value":"tpope/vim-fugitive"}]},{"type":"text","value":", it is necessary to configure the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"gpg-agent"}]},{"type":"text","value":" to use a GUI based "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-program"}]},{"type":"text","value":"."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In order to sign git commits from within Vim using a plugin like "},{"type":"element","tag":"a","props":{"href":"https://github.com/tpope/vim-fugitive","rel":["nofollow"]},"children":[{"type":"text","value":"tpope/vim-fugitive"}]},{"type":"text","value":", it is necessary to configure the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"gpg-agent"}]},{"type":"text","value":" to use a GUI based "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-program"}]},{"type":"text","value":"."}]},{"type":"element","tag":"h2","props":{"id":"preface"},"children":[{"type":"text","value":"Preface"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The man, the myth, the legend, Timothy Popallopollis himself "},{"type":"element","tag":"a","props":{"href":"https://github.com/tpope/vim-fugitive/issues/846#issuecomment-253816577","rel":["nofollow"]},"children":[{"type":"text","value":"recommends"}]},{"type":"text","value":" configuring your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"gpg-agent"}]},{"type":"text","value":" to use a GUI based "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-program"}]},{"type":"text","value":". On macOS this can be done quite by simply installing "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-mac"}]},{"type":"text","value":", and updating your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"gpg-agent.conf"}]},{"type":"text","value":"."}]},{"type":"element","tag":"h2","props":{"id":"configuration"},"children":[{"type":"text","value":"Configuration"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First things first, let's install the pinentry program."}]},{"type":"element","tag":"pre","props":{"code":"$ brew install pinentry-mac\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" brew"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pinentry-mac\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, all we need to do is set the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-program"}]},{"type":"text","value":" option in your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"~/.gnupg/gpg-agent.conf"}]},{"type":"text","value":" file."}]},{"type":"element","tag":"pre","props":{"code":"default-cache-ttl 600\nmax-cache-ttl 7200\npinentry-program /opt/homebrew/bin/pinentry-mac\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"default-cache-ttl 600\nmax-cache-ttl 7200\npinentry-program /opt/homebrew/bin/pinentry-mac\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If your don't know the path to your pinentry program, you can throw down a quick "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"which"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"code":"$ which pinentry-mac\n/opt/homebrew/bin/pinentry-mac\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" which"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pinentry-mac\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"/opt/homebrew/bin/pinentry-mac\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Or use your Homebrew prefix."}]},{"type":"element","tag":"pre","props":{"code":"$ echo $(brew --prefix)/bin/pinentry-mac\n/opt/homebrew/bin/pinentry-mac\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" echo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" $("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"brew"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --prefix"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":")/bin/pinentry-mac\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"/opt/homebrew/bin/pinentry-mac\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"But that's all it takes. Now, you should be prompted to enter your gpg pin in an external window when signing commits from vim."}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"preface","depth":2,"text":"Preface"},{"id":"configuration","depth":2,"text":"Configuration"}]}},"_type":"markdown","_id":"content:articles:vim-fugitive-gpg-pinentry.md","_source":"content","_file":"articles/vim-fugitive-gpg-pinentry.md","_extension":"md"}],"navigation":[{"title":"Articles","_path":"/articles","children":[{"title":"Upgrading the Firmware on the PCEngines APU2","_path":"/articles/apu2-firmware-upgrade"},{"title":"Docker Volume Permissions with SELinux","_path":"/articles/docker-selinux-volumes"},{"title":"Exploring the Digital Ocean `doctl` Utility","_path":"/articles/doctl"},{"title":"Impressions of Fennel with Hammerspoon","_path":"/articles/fennel-initial-exploration"},{"title":"Migrate to TrueNAS Scale from TrueNAS Core","_path":"/articles/migrate-truenas-from-core-to-scale"},{"title":"How To Add an RSS Feed to a Nuxt Website","_path":"/articles/nuxt-content-rss-feed"},{"title":"This Website Has Been Migrated to Nuxt 3 🎉","_path":"/articles/nuxt-v3-migration"},{"title":"Create a Persistent Arch Linux Bootable USB with Vagrant","_path":"/articles/persistent-archlinux-usb"},{"title":"Easily Transcribe Podcasts with Whisper.cpp","_path":"/articles/podcast-transcription-whispercpp"},{"title":"Tip: Re-running Bash Commands","_path":"/articles/quick-tip-rerunning-bash-commands"},{"title":"Reset IPMI Credentials from the Host OS","_path":"/articles/reset-ipmi-password-from-host-os"},{"title":"Configuring a YubiKey for use with OpenSSH","_path":"/articles/ssh-ed25519-sk-yubikey"},{"title":"Unit Testing in MicroPython with Mocks","_path":"/articles/unit-testing-micropython-with-mocks"},{"title":"Using pinentry-mac to sign commits from vim-fugitive","_path":"/articles/vim-fugitive-gpg-pinentry"}]}]} \ No newline at end of file diff --git a/api/_content/query/QmL7G3Pk7i.1726174725311.json b/api/_content/query/0ikQYfLQVZ.1727638383380.json similarity index 99% rename from api/_content/query/QmL7G3Pk7i.1726174725311.json rename to api/_content/query/0ikQYfLQVZ.1727638383380.json index a742e40e..5eddad60 100644 --- a/api/_content/query/QmL7G3Pk7i.1726174725311.json +++ b/api/_content/query/0ikQYfLQVZ.1727638383380.json @@ -1 +1 @@ -{"_path":"/articles/unit-testing-micropython-with-mocks","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Unit Testing in MicroPython with Mocks","description":"Unit testing code for embedded systems can be challenging. While it's possible\nto leverage emulators, write side-effect free code, or run tests on the\nhardware itself, it's often easiest to unit test the code on your personal\ncomputer with mocked hardware functionality.","date":"2020-02-07","draft":false,"tags":["micropython","testing","mocks","tutorial"],"categories":["python","embedded"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Unit testing code for embedded systems can be challenging. While it's possible\nto leverage emulators, write side-effect free code, or run tests on the\nhardware itself, it's often easiest to unit test the code on your personal\ncomputer with mocked hardware functionality."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Unit testing code for embedded systems can be challenging. While it's possible\nto leverage emulators, write side-effect free code, or run tests on the\nhardware itself, it's often easiest to unit test the code on your personal\ncomputer with mocked hardware functionality."}]},{"type":"element","tag":"h1","props":{"id":"mocking"},"children":[{"type":"text","value":"Mocking"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Mocks allow us to replace the hardware interfacing functionality under-the-hood\nwith predefined results and side-effects. For example, if there is a piece of\nlogic that retrieves values from an accelerometer to get a device's\norientation, it would be possible to mock the returned values of the\naccelerometer -- allowing us to run the unit tests on a device that does not\nhave an accelerometer sensor installed."}]},{"type":"element","tag":"h1","props":{"id":"a-micropython-mocking-example"},"children":[{"type":"text","value":"A MicroPython Mocking Example"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In this example, we will be unit testing a module named "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"time_logger"}]},{"type":"text","value":", that\ndepends on the MicroPython library "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime"}]},{"type":"text","value":" to log the most recent Epoch time to\na file."}]},{"type":"element","tag":"pre","props":{"className":"language-python shiki shiki-themes github-light","code":"# time_logger.py\n\nclass TimeLogger(object):\n\n def save_time(self):\n \"\"\" Overwrite a file with the most recent Epoch timestamp from `utime`\n \"\"\"\n with open(\"LAST_KNOWN_TIME\", \"w+\") as f:\n f.write(str(utime.time()))\n","language":"python","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# time_logger.py\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"class"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" TimeLogger"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"object"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" def"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" save_time"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(self):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"\"\" Overwrite a file with the most recent Epoch timestamp from `utime`\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"\"\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" with"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" open"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"LAST_KNOWN_TIME\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"w+\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"as"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" f:\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" f.write("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"str"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(utime.time()))\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, because the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime"}]},{"type":"text","value":" module is not installed on the machine that the unit\ntests on, we must mock "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime"}]},{"type":"text","value":" module before importing "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"time_logger"}]},{"type":"text","value":" in our\nunit test file."}]},{"type":"element","tag":"pre","props":{"className":"language-python shiki shiki-themes github-light","code":"# test_time_logger.py\n\nimport unittest\n\nfrom unittest.mock import MagicMock\n\nsys.modules['utime'] = MagicMock()\nfrom time_logger import TimeLogger\n","language":"python","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# test_time_logger.py\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" unittest\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" unittest.mock "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" MagicMock\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"sys.modules["}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'utime'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"] "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" MagicMock()\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" time_logger "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" TimeLogger\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, we can write a test that patches the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime.time"}]},{"type":"text","value":" functionality so that\nit returns a value of our choosing -- in this case, "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"1234"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-python shiki shiki-themes github-light","code":"class TestTimeLogger(unittest.TestCase):\n\n def test_save_time(self):\n \"\"\" Verify that the Epoch time is written to file\n \"\"\"\n with unittest.mock.patch(\"utime.time\", return_value=1234):\n t = TimeLogger()\n t.save_time()\n with open(\"LAST_KNOWN_TIME\") as f:\n self.assertEqual(\"1234\", f.read())\n","language":"python","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"class"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" TestTimeLogger"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"unittest"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"TestCase"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" def"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" test_save_time"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(self):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"\"\" Verify that the Epoch time is written to file\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"\"\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" with"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" unittest.mock.patch("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"utime.time\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"return_value"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"1234"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" t "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" TimeLogger()\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" t.save_time()\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" with"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" open"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"LAST_KNOWN_TIME\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"as"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" f:\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" self"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":".assertEqual("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"1234\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", f.read())\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Now, when the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"save_time"}]},{"type":"text","value":" method gets the latest time from "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime.time()"}]},{"type":"text","value":", the\nvalue will be patched to return "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"1234"}]},{"type":"text","value":". That value will be written to a file,\nand our unit test will pass!"}]},{"type":"element","tag":"h2","props":{"id":"references"},"children":[{"type":"text","value":"References"}]},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.python.org/3/library/unittest.html","rel":["nofollow"]},"children":[{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"unittest"}]},{"type":"text","value":" — Unit testing framework"}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"references","depth":2,"text":"References"}]}},"_type":"markdown","_id":"content:articles:unit-testing-micropython-with-mocks.md","_source":"content","_file":"articles/unit-testing-micropython-with-mocks.md","_stem":"articles/unit-testing-micropython-with-mocks","_extension":"md"} \ No newline at end of file +{"_path":"/articles/unit-testing-micropython-with-mocks","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Unit Testing in MicroPython with Mocks","description":"Unit testing code for embedded systems can be challenging. While it's possible\nto leverage emulators, write side-effect free code, or run tests on the\nhardware itself, it's often easiest to unit test the code on your personal\ncomputer with mocked hardware functionality.","date":"2020-02-07","draft":false,"tags":["micropython","testing","mocks","tutorial"],"categories":["python","embedded"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Unit testing code for embedded systems can be challenging. While it's possible\nto leverage emulators, write side-effect free code, or run tests on the\nhardware itself, it's often easiest to unit test the code on your personal\ncomputer with mocked hardware functionality."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Unit testing code for embedded systems can be challenging. While it's possible\nto leverage emulators, write side-effect free code, or run tests on the\nhardware itself, it's often easiest to unit test the code on your personal\ncomputer with mocked hardware functionality."}]},{"type":"element","tag":"h1","props":{"id":"mocking"},"children":[{"type":"text","value":"Mocking"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Mocks allow us to replace the hardware interfacing functionality under-the-hood\nwith predefined results and side-effects. For example, if there is a piece of\nlogic that retrieves values from an accelerometer to get a device's\norientation, it would be possible to mock the returned values of the\naccelerometer -- allowing us to run the unit tests on a device that does not\nhave an accelerometer sensor installed."}]},{"type":"element","tag":"h1","props":{"id":"a-micropython-mocking-example"},"children":[{"type":"text","value":"A MicroPython Mocking Example"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In this example, we will be unit testing a module named "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"time_logger"}]},{"type":"text","value":", that\ndepends on the MicroPython library "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime"}]},{"type":"text","value":" to log the most recent Epoch time to\na file."}]},{"type":"element","tag":"pre","props":{"className":"language-python shiki shiki-themes github-light","code":"# time_logger.py\n\nclass TimeLogger(object):\n\n def save_time(self):\n \"\"\" Overwrite a file with the most recent Epoch timestamp from `utime`\n \"\"\"\n with open(\"LAST_KNOWN_TIME\", \"w+\") as f:\n f.write(str(utime.time()))\n","language":"python","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# time_logger.py\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"class"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" TimeLogger"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"object"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" def"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" save_time"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(self):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"\"\" Overwrite a file with the most recent Epoch timestamp from `utime`\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"\"\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" with"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" open"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"LAST_KNOWN_TIME\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"w+\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"as"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" f:\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" f.write("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"str"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(utime.time()))\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, because the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime"}]},{"type":"text","value":" module is not installed on the machine that the unit\ntests on, we must mock "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime"}]},{"type":"text","value":" module before importing "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"time_logger"}]},{"type":"text","value":" in our\nunit test file."}]},{"type":"element","tag":"pre","props":{"className":"language-python shiki shiki-themes github-light","code":"# test_time_logger.py\n\nimport unittest\n\nfrom unittest.mock import MagicMock\n\nsys.modules['utime'] = MagicMock()\nfrom time_logger import TimeLogger\n","language":"python","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# test_time_logger.py\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" unittest\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" unittest.mock "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" MagicMock\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"sys.modules["}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'utime'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"] "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" MagicMock()\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" time_logger "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" TimeLogger\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, we can write a test that patches the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime.time"}]},{"type":"text","value":" functionality so that\nit returns a value of our choosing -- in this case, "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"1234"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-python shiki shiki-themes github-light","code":"class TestTimeLogger(unittest.TestCase):\n\n def test_save_time(self):\n \"\"\" Verify that the Epoch time is written to file\n \"\"\"\n with unittest.mock.patch(\"utime.time\", return_value=1234):\n t = TimeLogger()\n t.save_time()\n with open(\"LAST_KNOWN_TIME\") as f:\n self.assertEqual(\"1234\", f.read())\n","language":"python","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"class"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" TestTimeLogger"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"unittest"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"TestCase"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" def"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" test_save_time"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(self):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"\"\" Verify that the Epoch time is written to file\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"\"\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" with"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" unittest.mock.patch("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"utime.time\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"return_value"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"1234"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"):\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" t "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" TimeLogger()\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" t.save_time()\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" with"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" open"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"LAST_KNOWN_TIME\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"as"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" f:\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" self"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":".assertEqual("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"1234\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", f.read())\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Now, when the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"save_time"}]},{"type":"text","value":" method gets the latest time from "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"utime.time()"}]},{"type":"text","value":", the\nvalue will be patched to return "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"1234"}]},{"type":"text","value":". That value will be written to a file,\nand our unit test will pass!"}]},{"type":"element","tag":"h2","props":{"id":"references"},"children":[{"type":"text","value":"References"}]},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.python.org/3/library/unittest.html","rel":["nofollow"]},"children":[{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"unittest"}]},{"type":"text","value":" — Unit testing framework"}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"references","depth":2,"text":"References"}]}},"_type":"markdown","_id":"content:articles:unit-testing-micropython-with-mocks.md","_source":"content","_file":"articles/unit-testing-micropython-with-mocks.md","_extension":"md"} \ No newline at end of file diff --git a/api/_content/query/XgcK3x9EBy.1726174725311.json b/api/_content/query/0vuDGaHulu.1727638383380.json similarity index 99% rename from api/_content/query/XgcK3x9EBy.1726174725311.json rename to api/_content/query/0vuDGaHulu.1727638383380.json index a5d0be1f..f9ccd20f 100644 --- a/api/_content/query/XgcK3x9EBy.1726174725311.json +++ b/api/_content/query/0vuDGaHulu.1727638383380.json @@ -1 +1 @@ -{"_path":"/articles/persistent-archlinux-usb","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Create a Persistent Arch Linux Bootable USB with Vagrant","description":"When installing a linux distribution, it is common for the instructions to have\nthe user create a bootable USB, boot from the device, and proceed with the\ninstallation procedure from that live medium. However, this blog post will\noutline an alternative approach where a virtual machine created with Vagrant\nwill be used in favor of the live medium.","date":"2020-01-09","draft":false,"tags":["vagrant","archlinux"],"categories":["linux"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"When installing a linux distribution, it is common for the instructions to have\nthe user create a bootable USB, boot from the device, and proceed with the\ninstallation procedure from that live medium. However, this blog post will\noutline an alternative approach where a virtual machine created with Vagrant\nwill be used in favor of the live medium."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"When installing a linux distribution, it is common for the instructions to have\nthe user create a bootable USB, boot from the device, and proceed with the\ninstallation procedure from that live medium. However, this blog post will\noutline an alternative approach where a virtual machine created with Vagrant\nwill be used in favor of the live medium."}]},{"type":"element","tag":"h1","props":{"id":"preface"},"children":[{"type":"text","value":"Preface"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The original intention was to use Docker for this process -- leveraging the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--device"}]},{"type":"text","value":" flag and mounting the target USB device in the Docker container,\nbut the underlying hypervisor in Docker Desktop for Mac does not support this.\n"},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.docker.com/docker-for-mac/docker-toolbox/","rel":["nofollow"]},"children":[{"type":"text","value":"1"}]},{"type":"text","value":" "},{"type":"element","tag":"a","props":{"href":"https://github.com/moby/hyperkit","rel":["nofollow"]},"children":[{"type":"text","value":"2"}]},{"type":"text","value":" "},{"type":"element","tag":"a","props":{"href":"https://github.com/docker/for-mac/issues/900","rel":["nofollow"]},"children":[{"type":"text","value":"3"}]}]},{"type":"text","value":" While there are workarounds using Docker\nMachine, Vagrant felt like the path of least resistance."}]},{"type":"element","tag":"h1","props":{"id":"instructions"},"children":[{"type":"text","value":"Instructions"}]},{"type":"element","tag":"h2","props":{"id":"create-an-arch-linux-virtual-machine-with-vagrant"},"children":[{"type":"text","value":"Create an Arch Linux Virtual Machine with Vagrant"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Get the latest Arch Linux image "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://app.vagrantup.com/archlinux/boxes/archlinux","rel":["nofollow"]},"children":[{"type":"text","value":"4"}]}]},{"type":"text","value":" from the Vagrant Cloud Box\nCatalog."}]},{"type":"element","tag":"pre","props":{"code":"vagrant box add archlinux/archlinux\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"vagrant"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" box"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" add"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" archlinux/archlinux\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Determine the USB vendor information for the thumb-drive that we will\npass-through to the virtual machine. Using the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"VBoxManage"}]},{"type":"text","value":" utility that comes\nwith Virtual Box, list the devices, and make note of the Vendor and Product ID."}]},{"type":"element","tag":"pre","props":{"code":" VBoxManage list usbhost\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" VBoxManage"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" usbhost\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Create a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Vagrantfile"}]},{"type":"text","value":" with "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"archlinx/archlinux"}]},{"type":"text","value":" as the target box, and the USB\ndevice information that is passed through. "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://antonyjepson.wordpress.com/2012/01/26/quickly-attaching-usb-devices-to-virtualbox-guests-using-vboxmanage/","rel":["nofollow"]},"children":[{"type":"text","value":"5"}]},{"type":"text","value":" "},{"type":"element","tag":"a","props":{"href":"https://gist.github.com/dscape/7d829c0c116ef419f963","rel":["nofollow"]},"children":[{"type":"text","value":"6"}]}]},{"type":"text","value":" Vagrant\noffers a handy customization parameter "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"vb.customize"}]},{"type":"text","value":" that calls the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"VBoxManage"}]},{"type":"text","value":" command under-the-hood, allowing one to enable the guest machine\nto access the host machine's USB devices."}]},{"type":"element","tag":"pre","props":{"code":"# -*- mode: ruby -*-\n# vi: set ft=ruby :\n\nVagrant.configure(\"2\") do |config|\n config.vm.box = \"archlinux/archlinux\"\n config.vm.provider \"virtualbox\" do |vb|\n vb.name = \"archlinux\"\n vb.customize ['modifyvm', :id, '--usb', 'on']\n vb.customize ['usbfilter', 'add', '1', '--target', :id, '--name', 'SanDisk Ultra Fit', '--vendorid', '0x0781', '--productid', '0x5583']\n end\nend\n","language":"txt","meta":"","className":"language-txt shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"# -*- mode: ruby -*-\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"# vi: set ft=ruby :\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Vagrant.configure(\"2\") do |config|\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" config.vm.box = \"archlinux/archlinux\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" config.vm.provider \"virtualbox\" do |vb|\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" vb.name = \"archlinux\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" vb.customize ['modifyvm', :id, '--usb', 'on']\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" vb.customize ['usbfilter', 'add', '1', '--target', :id, '--name', 'SanDisk Ultra Fit', '--vendorid', '0x0781', '--productid', '0x5583']\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" end\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"end\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"When virtual machine is brought up, the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"usbfilter"}]},{"type":"text","value":" is applied, and the guest\nis able to access to the host machine's USB device that was specified in the\nfilter."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Start the machine, "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ssh"}]},{"type":"text","value":" into the guest, and list the devices to confirm that\nthe USB device is available (see: "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"/dev/sdb"}]},{"type":"text","value":")."}]},{"type":"element","tag":"pre","props":{"code":"$ vagrant up\n$ vagrant ssh\n[vagrant@archlinux ~]$ lsblk\nNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT\nsda 8:0 0 20G 0 disk\n├─sda1 8:1 0 1.9G 0 part [SWAP]\n└─sda2 8:2 0 18.1G 0 part /\nsdb 8:16 1 28.7G 0 disk\n└─sdb1 8:17 1 8G 0 part\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" vagrant"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" up\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" vagrant"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ssh\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[vagrant@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]$ lsblk\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" MAJ:MIN"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" RM"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" SIZE"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" RO"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" TYPE"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" MOUNTPOINT\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sda"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 20G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" disk\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"├─sda1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 1.9G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" part"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" [SWAP]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"└─sda2"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:2"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 18.1G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" part"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" /\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sdb"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:16"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 28.7G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" disk\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"└─sdb1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:17"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" part\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"install-arch-linux-on-the-usb-drive"},"children":[{"type":"text","value":"Install Arch Linux on the USB Drive"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The "},{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/Installation_guide","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Installation Guide"}]},{"type":"text","value":" outlines the installation procedure in\ngreat detail -- the following steps follow this closely with a few alteration\ndue to installing onto removable media."}]},{"type":"element","tag":"h3","props":{"id":"partition-the-disk-uefi-with-gpt"},"children":[{"type":"text","value":"Partition the Disk (UEFI with GPT)"}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# fdisk /dev/sdb\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# fdisk /dev/sdb\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"code":"Command (m for help): p\nDisk /dev/sdb: 28.66 GiB, 30752636928 bytes, 60063744 sectors\nDisk model: Ultra Fit\nUnits: sectors of 1 * 512 = 512 bytes\nSector size (logical/physical): 512 bytes / 512 bytes\nI/O size (minimum/optimal): 512 bytes / 512 bytes\nDisklabel type: gpt\nDisk identifier: E1D6C445-1B79-AB4D-A442-FA4AD6DF4ECC\n\nDevice Start End Sectors Size Type\n/dev/sdb1 2048 1050623 1048576 512M EFI System\n/dev/sdb2 1050624 60063710 59013087 28.1G Linux filesystem\n\nFilesystem/RAID signature on partition 1 will be wiped.\n","language":"txt","meta":"","className":"language-txt shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Command (m for help): p\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Disk /dev/sdb: 28.66 GiB, 30752636928 bytes, 60063744 sectors\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Disk model: Ultra Fit\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Units: sectors of 1 * 512 = 512 bytes\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Sector size (logical/physical): 512 bytes / 512 bytes\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"I/O size (minimum/optimal): 512 bytes / 512 bytes\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Disklabel type: gpt\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Disk identifier: E1D6C445-1B79-AB4D-A442-FA4AD6DF4ECC\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Device Start End Sectors Size Type\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"/dev/sdb1 2048 1050623 1048576 512M EFI System\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":12},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"/dev/sdb2 1050624 60063710 59013087 28.1G Linux filesystem\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":13},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":14},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Filesystem/RAID signature on partition 1 will be wiped.\n"}]}]}]}]},{"type":"element","tag":"h3","props":{"id":"format-the-partitions"},"children":[{"type":"text","value":"Format the Partitions"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The UEFI specification mandates support for FAT file-systems, and FAT32 is\nrecommended for removable media. "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/EFI_system_partition#Format_the_partition","rel":["nofollow"]},"children":[{"type":"text","value":"7"}]}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# pacman -Sy dosfstools\n[root@archlinux ~]# mkfs.fat -F32 /dev/sdb1\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# pacman -Sy dosfstools\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mkfs.fat -F32 /dev/sdb1\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"As for the root partition, it is recommended to use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ext4"}]},{"type":"text","value":" without a journal to\nreduce the reads and writes to the file-system as this is detrimental to the\nflash-based USB drive. "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/Install_Arch_Linux_on_a_USB_key#Installation_tweaks","rel":["nofollow"]},"children":[{"type":"text","value":"8"}]}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# mkfs.ext4 -O \"^has_journal\" /dev/sdb2\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mkfs.ext4 -O "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"^has_journal\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" /dev/sdb2\n"}]}]}]}]},{"type":"element","tag":"h3","props":{"id":"mount-the-partitions-and-bootstrap-the-environment"},"children":[{"type":"text","value":"Mount the Partitions and Bootstrap the Environment"}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# mount /dev/sdb2 /mnt\n[root@archlinux ~]# mkdir -p /mnt/boot/efi\n[root@archlinux ~]# mount /dev/sdb1 /mnt/boot/efi\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mount /dev/sdb2 /mnt\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mkdir -p /mnt/boot/efi\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mount /dev/sdb1 /mnt/boot/efi\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# pacman -S arch-install-scripts\n[root@archlinux ~]# pacstrap /mnt base linux linux-firmware\n[root@archlinux ~]# genfstab -U /mnt >> /mnt/etc/fstab\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# pacman -S arch-install-scripts\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# pacstrap /mnt base linux linux-firmware\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# genfstab -U /mnt "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":">>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" /mnt/etc/fstab\n"}]}]}]}]},{"type":"element","tag":"h3","props":{"id":"configure-the-new-environment"},"children":[{"type":"text","value":"Configure the New Environment"}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# arch-chroot /mnt\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"[root@archlinux ~]# arch-chroot /mnt\n"}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux /]# ln -sf /usr/share/zoneinfo/US/Eastern /etc/localtime\n[root@archlinux /]# hwclock --systohc\n[root@archlinux /]# sed -i 's/#en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen\n[root@archlinux /]# locale-gen\n[root@archlinux /]# echo \"LANG=en_US.UTF-8\" > /etc/locale.conf\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"[root@archlinux /]# ln -sf /usr/share/zoneinfo/US/Eastern /etc/localtime\n[root@archlinux /]# hwclock --systohc\n[root@archlinux /]# sed -i 's/#en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen\n[root@archlinux /]# locale-gen\n[root@archlinux /]# echo \"LANG=en_US.UTF-8\" > /etc/locale.conf\n"}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux /]# hostnamectl set-hostname usb\n[root@archlinux /]# echo \"127.0.0.1 localhost\" >> /etc/hosts\n[root@archlinux /]# echo \"::1 localhost\" >> /etc/hosts\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"[root@archlinux /]# hostnamectl set-hostname usb\n[root@archlinux /]# echo \"127.0.0.1 localhost\" >> /etc/hosts\n[root@archlinux /]# echo \"::1 localhost\" >> /etc/hosts\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Note, one difference here from a standard installation is that the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--removable"}]},{"type":"text","value":" flag is specified when installing the GRUB bootloader.\n"},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/GRUB#UEFI_systems","rel":["nofollow"]},"children":[{"type":"text","value":"10"}]}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux /]# pacman -S grub\n[root@archlinux /]# grub-install --target=x86_64-efi --efi-directory=/boot/efi --removable --recheck\n[root@usb /]# grub-mkconfig -o /boot/grub/grub.cfg\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"[root@archlinux /]# pacman -S grub\n[root@archlinux /]# grub-install --target=x86_64-efi --efi-directory=/boot/efi --removable --recheck\n[root@usb /]# grub-mkconfig -o /boot/grub/grub.cfg\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Shutdown the virtual machine, restart the host machine, and boot the newly\ncreated Arch Linux thumb-drive!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"🎉"}]},{"type":"element","tag":"h2","props":{"id":"side-note"},"children":[{"type":"text","value":"Side-note"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"It was attempted to use the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"controlvm usbattach"}]},{"type":"text","value":" command to pass the USB\ndevice to the guest machine, but this did not work as it expects the virtual\nmachine to already be running, and the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"vb.customize"}]},{"type":"text","value":" option runs prior to\nbooting the machine. "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://www.vagrantup.com/docs/virtualbox/configuration.html#vboxmanage-customizations","rel":["nofollow"]},"children":[{"type":"text","value":"11"}]}]}]},{"type":"element","tag":"pre","props":{"code":"Command: [\"controlvm\", \"060a716b-1965-49e2-bc56-12beed5df716\", \"usbattach36fc9e60-c465-11cf-8056-444553540000\"]\n\nStderr: VBoxManage.exe: error: Machine '060a716b-1965-49e2-bc56-12beed5df716' is not currently running.\n","language":"txt","meta":"","className":"language-txt shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Command: [\"controlvm\", \"060a716b-1965-49e2-bc56-12beed5df716\", \"usbattach36fc9e60-c465-11cf-8056-444553540000\"]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Stderr: VBoxManage.exe: error: Machine '060a716b-1965-49e2-bc56-12beed5df716' is not currently running.\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"references"},"children":[{"type":"text","value":"References"}]},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.docker.com/docker-for-mac/docker-toolbox/","rel":["nofollow"]},"children":[{"type":"text","value":"Docker Desktop on Mac vs. Docker Toolbox"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/moby/hyperkit","rel":["nofollow"]},"children":[{"type":"text","value":"GitHub - HyperKit"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/docker/for-mac/issues/900","rel":["nofollow"]},"children":[{"type":"text","value":"GitHub - Docker for Mac - Issue #900"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://app.vagrantup.com/archlinux/boxes/archlinux","rel":["nofollow"]},"children":[{"type":"text","value":"Vagrant Cloud - Arch Linux"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://antonyjepson.wordpress.com/2012/01/26/quickly-attaching-usb-devices-to-virtualbox-guests-using-vboxmanage/","rel":["nofollow"]},"children":[{"type":"text","value":"Attaching USB Devices to VirtualBox Guests using VBoxManage"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://gist.github.com/dscape/7d829c0c116ef419f963","rel":["nofollow"]},"children":[{"type":"text","value":"GitHub Gist - Vagrant USB Filter"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/EFI_system_partition#Format_the_partition","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Wiki - EFI System Partition - Format Partitions"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/Install_Arch_Linux_on_a_USB_key#Installation_tweaks","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Wiki - Arch Linux on USB - Installation Tweaks"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/Installation_guide","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Wiki - Installation Guide"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/GRUB#UEFI_systems","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Wiki - GRUB - UEFI Systems"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://www.vagrantup.com/docs/virtualbox/configuration.html#vboxmanage-customizations","rel":["nofollow"]},"children":[{"type":"text","value":"Vagrant VBoxManage Customizations "}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"create-an-arch-linux-virtual-machine-with-vagrant","depth":2,"text":"Create an Arch Linux Virtual Machine with Vagrant"},{"id":"install-arch-linux-on-the-usb-drive","depth":2,"text":"Install Arch Linux on the USB Drive","children":[{"id":"partition-the-disk-uefi-with-gpt","depth":3,"text":"Partition the Disk (UEFI with GPT)"},{"id":"format-the-partitions","depth":3,"text":"Format the Partitions"},{"id":"mount-the-partitions-and-bootstrap-the-environment","depth":3,"text":"Mount the Partitions and Bootstrap the Environment"},{"id":"configure-the-new-environment","depth":3,"text":"Configure the New Environment"}]},{"id":"side-note","depth":2,"text":"Side-note"},{"id":"references","depth":2,"text":"References"}]}},"_type":"markdown","_id":"content:articles:persistent-archlinux-usb.md","_source":"content","_file":"articles/persistent-archlinux-usb.md","_stem":"articles/persistent-archlinux-usb","_extension":"md"} \ No newline at end of file +{"_path":"/articles/persistent-archlinux-usb","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Create a Persistent Arch Linux Bootable USB with Vagrant","description":"When installing a linux distribution, it is common for the instructions to have\nthe user create a bootable USB, boot from the device, and proceed with the\ninstallation procedure from that live medium. However, this blog post will\noutline an alternative approach where a virtual machine created with Vagrant\nwill be used in favor of the live medium.","date":"2020-01-09","draft":false,"tags":["vagrant","archlinux"],"categories":["linux"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"When installing a linux distribution, it is common for the instructions to have\nthe user create a bootable USB, boot from the device, and proceed with the\ninstallation procedure from that live medium. However, this blog post will\noutline an alternative approach where a virtual machine created with Vagrant\nwill be used in favor of the live medium."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"When installing a linux distribution, it is common for the instructions to have\nthe user create a bootable USB, boot from the device, and proceed with the\ninstallation procedure from that live medium. However, this blog post will\noutline an alternative approach where a virtual machine created with Vagrant\nwill be used in favor of the live medium."}]},{"type":"element","tag":"h1","props":{"id":"preface"},"children":[{"type":"text","value":"Preface"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The original intention was to use Docker for this process -- leveraging the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--device"}]},{"type":"text","value":" flag and mounting the target USB device in the Docker container,\nbut the underlying hypervisor in Docker Desktop for Mac does not support this.\n"},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.docker.com/docker-for-mac/docker-toolbox/","rel":["nofollow"]},"children":[{"type":"text","value":"1"}]},{"type":"text","value":" "},{"type":"element","tag":"a","props":{"href":"https://github.com/moby/hyperkit","rel":["nofollow"]},"children":[{"type":"text","value":"2"}]},{"type":"text","value":" "},{"type":"element","tag":"a","props":{"href":"https://github.com/docker/for-mac/issues/900","rel":["nofollow"]},"children":[{"type":"text","value":"3"}]}]},{"type":"text","value":" While there are workarounds using Docker\nMachine, Vagrant felt like the path of least resistance."}]},{"type":"element","tag":"h1","props":{"id":"instructions"},"children":[{"type":"text","value":"Instructions"}]},{"type":"element","tag":"h2","props":{"id":"create-an-arch-linux-virtual-machine-with-vagrant"},"children":[{"type":"text","value":"Create an Arch Linux Virtual Machine with Vagrant"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Get the latest Arch Linux image "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://app.vagrantup.com/archlinux/boxes/archlinux","rel":["nofollow"]},"children":[{"type":"text","value":"4"}]}]},{"type":"text","value":" from the Vagrant Cloud Box\nCatalog."}]},{"type":"element","tag":"pre","props":{"code":"vagrant box add archlinux/archlinux\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"vagrant"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" box"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" add"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" archlinux/archlinux\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Determine the USB vendor information for the thumb-drive that we will\npass-through to the virtual machine. Using the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"VBoxManage"}]},{"type":"text","value":" utility that comes\nwith Virtual Box, list the devices, and make note of the Vendor and Product ID."}]},{"type":"element","tag":"pre","props":{"code":" VBoxManage list usbhost\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" VBoxManage"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" usbhost\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Create a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Vagrantfile"}]},{"type":"text","value":" with "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"archlinx/archlinux"}]},{"type":"text","value":" as the target box, and the USB\ndevice information that is passed through. "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://antonyjepson.wordpress.com/2012/01/26/quickly-attaching-usb-devices-to-virtualbox-guests-using-vboxmanage/","rel":["nofollow"]},"children":[{"type":"text","value":"5"}]},{"type":"text","value":" "},{"type":"element","tag":"a","props":{"href":"https://gist.github.com/dscape/7d829c0c116ef419f963","rel":["nofollow"]},"children":[{"type":"text","value":"6"}]}]},{"type":"text","value":" Vagrant\noffers a handy customization parameter "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"vb.customize"}]},{"type":"text","value":" that calls the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"VBoxManage"}]},{"type":"text","value":" command under-the-hood, allowing one to enable the guest machine\nto access the host machine's USB devices."}]},{"type":"element","tag":"pre","props":{"code":"# -*- mode: ruby -*-\n# vi: set ft=ruby :\n\nVagrant.configure(\"2\") do |config|\n config.vm.box = \"archlinux/archlinux\"\n config.vm.provider \"virtualbox\" do |vb|\n vb.name = \"archlinux\"\n vb.customize ['modifyvm', :id, '--usb', 'on']\n vb.customize ['usbfilter', 'add', '1', '--target', :id, '--name', 'SanDisk Ultra Fit', '--vendorid', '0x0781', '--productid', '0x5583']\n end\nend\n","language":"txt","meta":"","className":"language-txt shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"# -*- mode: ruby -*-\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"# vi: set ft=ruby :\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Vagrant.configure(\"2\") do |config|\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" config.vm.box = \"archlinux/archlinux\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" config.vm.provider \"virtualbox\" do |vb|\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" vb.name = \"archlinux\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" vb.customize ['modifyvm', :id, '--usb', 'on']\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" vb.customize ['usbfilter', 'add', '1', '--target', :id, '--name', 'SanDisk Ultra Fit', '--vendorid', '0x0781', '--productid', '0x5583']\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" end\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"end\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"When virtual machine is brought up, the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"usbfilter"}]},{"type":"text","value":" is applied, and the guest\nis able to access to the host machine's USB device that was specified in the\nfilter."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Start the machine, "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ssh"}]},{"type":"text","value":" into the guest, and list the devices to confirm that\nthe USB device is available (see: "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"/dev/sdb"}]},{"type":"text","value":")."}]},{"type":"element","tag":"pre","props":{"code":"$ vagrant up\n$ vagrant ssh\n[vagrant@archlinux ~]$ lsblk\nNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT\nsda 8:0 0 20G 0 disk\n├─sda1 8:1 0 1.9G 0 part [SWAP]\n└─sda2 8:2 0 18.1G 0 part /\nsdb 8:16 1 28.7G 0 disk\n└─sdb1 8:17 1 8G 0 part\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" vagrant"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" up\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" vagrant"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ssh\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[vagrant@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]$ lsblk\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" MAJ:MIN"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" RM"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" SIZE"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" RO"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" TYPE"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" MOUNTPOINT\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sda"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 20G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" disk\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"├─sda1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 1.9G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" part"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" [SWAP]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"└─sda2"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:2"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 18.1G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" part"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" /\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sdb"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:16"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 28.7G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" disk\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"└─sdb1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8:17"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 8G"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 0"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" part\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"install-arch-linux-on-the-usb-drive"},"children":[{"type":"text","value":"Install Arch Linux on the USB Drive"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The "},{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/Installation_guide","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Installation Guide"}]},{"type":"text","value":" outlines the installation procedure in\ngreat detail -- the following steps follow this closely with a few alteration\ndue to installing onto removable media."}]},{"type":"element","tag":"h3","props":{"id":"partition-the-disk-uefi-with-gpt"},"children":[{"type":"text","value":"Partition the Disk (UEFI with GPT)"}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# fdisk /dev/sdb\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# fdisk /dev/sdb\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"code":"Command (m for help): p\nDisk /dev/sdb: 28.66 GiB, 30752636928 bytes, 60063744 sectors\nDisk model: Ultra Fit\nUnits: sectors of 1 * 512 = 512 bytes\nSector size (logical/physical): 512 bytes / 512 bytes\nI/O size (minimum/optimal): 512 bytes / 512 bytes\nDisklabel type: gpt\nDisk identifier: E1D6C445-1B79-AB4D-A442-FA4AD6DF4ECC\n\nDevice Start End Sectors Size Type\n/dev/sdb1 2048 1050623 1048576 512M EFI System\n/dev/sdb2 1050624 60063710 59013087 28.1G Linux filesystem\n\nFilesystem/RAID signature on partition 1 will be wiped.\n","language":"txt","meta":"","className":"language-txt shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Command (m for help): p\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Disk /dev/sdb: 28.66 GiB, 30752636928 bytes, 60063744 sectors\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Disk model: Ultra Fit\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Units: sectors of 1 * 512 = 512 bytes\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Sector size (logical/physical): 512 bytes / 512 bytes\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"I/O size (minimum/optimal): 512 bytes / 512 bytes\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Disklabel type: gpt\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Disk identifier: E1D6C445-1B79-AB4D-A442-FA4AD6DF4ECC\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Device Start End Sectors Size Type\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"/dev/sdb1 2048 1050623 1048576 512M EFI System\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":12},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"/dev/sdb2 1050624 60063710 59013087 28.1G Linux filesystem\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":13},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":14},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Filesystem/RAID signature on partition 1 will be wiped.\n"}]}]}]}]},{"type":"element","tag":"h3","props":{"id":"format-the-partitions"},"children":[{"type":"text","value":"Format the Partitions"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The UEFI specification mandates support for FAT file-systems, and FAT32 is\nrecommended for removable media. "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/EFI_system_partition#Format_the_partition","rel":["nofollow"]},"children":[{"type":"text","value":"7"}]}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# pacman -Sy dosfstools\n[root@archlinux ~]# mkfs.fat -F32 /dev/sdb1\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# pacman -Sy dosfstools\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mkfs.fat -F32 /dev/sdb1\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"As for the root partition, it is recommended to use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ext4"}]},{"type":"text","value":" without a journal to\nreduce the reads and writes to the file-system as this is detrimental to the\nflash-based USB drive. "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/Install_Arch_Linux_on_a_USB_key#Installation_tweaks","rel":["nofollow"]},"children":[{"type":"text","value":"8"}]}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# mkfs.ext4 -O \"^has_journal\" /dev/sdb2\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mkfs.ext4 -O "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"^has_journal\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" /dev/sdb2\n"}]}]}]}]},{"type":"element","tag":"h3","props":{"id":"mount-the-partitions-and-bootstrap-the-environment"},"children":[{"type":"text","value":"Mount the Partitions and Bootstrap the Environment"}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# mount /dev/sdb2 /mnt\n[root@archlinux ~]# mkdir -p /mnt/boot/efi\n[root@archlinux ~]# mount /dev/sdb1 /mnt/boot/efi\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mount /dev/sdb2 /mnt\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mkdir -p /mnt/boot/efi\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# mount /dev/sdb1 /mnt/boot/efi\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# pacman -S arch-install-scripts\n[root@archlinux ~]# pacstrap /mnt base linux linux-firmware\n[root@archlinux ~]# genfstab -U /mnt >> /mnt/etc/fstab\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# pacman -S arch-install-scripts\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# pacstrap /mnt base linux linux-firmware\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[root@archlinux "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"~"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]# genfstab -U /mnt "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":">>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" /mnt/etc/fstab\n"}]}]}]}]},{"type":"element","tag":"h3","props":{"id":"configure-the-new-environment"},"children":[{"type":"text","value":"Configure the New Environment"}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux ~]# arch-chroot /mnt\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"[root@archlinux ~]# arch-chroot /mnt\n"}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux /]# ln -sf /usr/share/zoneinfo/US/Eastern /etc/localtime\n[root@archlinux /]# hwclock --systohc\n[root@archlinux /]# sed -i 's/#en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen\n[root@archlinux /]# locale-gen\n[root@archlinux /]# echo \"LANG=en_US.UTF-8\" > /etc/locale.conf\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"[root@archlinux /]# ln -sf /usr/share/zoneinfo/US/Eastern /etc/localtime\n[root@archlinux /]# hwclock --systohc\n[root@archlinux /]# sed -i 's/#en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen\n[root@archlinux /]# locale-gen\n[root@archlinux /]# echo \"LANG=en_US.UTF-8\" > /etc/locale.conf\n"}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux /]# hostnamectl set-hostname usb\n[root@archlinux /]# echo \"127.0.0.1 localhost\" >> /etc/hosts\n[root@archlinux /]# echo \"::1 localhost\" >> /etc/hosts\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"[root@archlinux /]# hostnamectl set-hostname usb\n[root@archlinux /]# echo \"127.0.0.1 localhost\" >> /etc/hosts\n[root@archlinux /]# echo \"::1 localhost\" >> /etc/hosts\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Note, one difference here from a standard installation is that the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--removable"}]},{"type":"text","value":" flag is specified when installing the GRUB bootloader.\n"},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/GRUB#UEFI_systems","rel":["nofollow"]},"children":[{"type":"text","value":"10"}]}]}]},{"type":"element","tag":"pre","props":{"code":"[root@archlinux /]# pacman -S grub\n[root@archlinux /]# grub-install --target=x86_64-efi --efi-directory=/boot/efi --removable --recheck\n[root@usb /]# grub-mkconfig -o /boot/grub/grub.cfg\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"[root@archlinux /]# pacman -S grub\n[root@archlinux /]# grub-install --target=x86_64-efi --efi-directory=/boot/efi --removable --recheck\n[root@usb /]# grub-mkconfig -o /boot/grub/grub.cfg\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Shutdown the virtual machine, restart the host machine, and boot the newly\ncreated Arch Linux thumb-drive!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"🎉"}]},{"type":"element","tag":"h2","props":{"id":"side-note"},"children":[{"type":"text","value":"Side-note"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"It was attempted to use the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"controlvm usbattach"}]},{"type":"text","value":" command to pass the USB\ndevice to the guest machine, but this did not work as it expects the virtual\nmachine to already be running, and the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"vb.customize"}]},{"type":"text","value":" option runs prior to\nbooting the machine. "},{"type":"element","tag":"sup","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://www.vagrantup.com/docs/virtualbox/configuration.html#vboxmanage-customizations","rel":["nofollow"]},"children":[{"type":"text","value":"11"}]}]}]},{"type":"element","tag":"pre","props":{"code":"Command: [\"controlvm\", \"060a716b-1965-49e2-bc56-12beed5df716\", \"usbattach36fc9e60-c465-11cf-8056-444553540000\"]\n\nStderr: VBoxManage.exe: error: Machine '060a716b-1965-49e2-bc56-12beed5df716' is not currently running.\n","language":"txt","meta":"","className":"language-txt shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Command: [\"controlvm\", \"060a716b-1965-49e2-bc56-12beed5df716\", \"usbattach36fc9e60-c465-11cf-8056-444553540000\"]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"Stderr: VBoxManage.exe: error: Machine '060a716b-1965-49e2-bc56-12beed5df716' is not currently running.\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"references"},"children":[{"type":"text","value":"References"}]},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.docker.com/docker-for-mac/docker-toolbox/","rel":["nofollow"]},"children":[{"type":"text","value":"Docker Desktop on Mac vs. Docker Toolbox"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/moby/hyperkit","rel":["nofollow"]},"children":[{"type":"text","value":"GitHub - HyperKit"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/docker/for-mac/issues/900","rel":["nofollow"]},"children":[{"type":"text","value":"GitHub - Docker for Mac - Issue #900"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://app.vagrantup.com/archlinux/boxes/archlinux","rel":["nofollow"]},"children":[{"type":"text","value":"Vagrant Cloud - Arch Linux"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://antonyjepson.wordpress.com/2012/01/26/quickly-attaching-usb-devices-to-virtualbox-guests-using-vboxmanage/","rel":["nofollow"]},"children":[{"type":"text","value":"Attaching USB Devices to VirtualBox Guests using VBoxManage"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://gist.github.com/dscape/7d829c0c116ef419f963","rel":["nofollow"]},"children":[{"type":"text","value":"GitHub Gist - Vagrant USB Filter"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/EFI_system_partition#Format_the_partition","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Wiki - EFI System Partition - Format Partitions"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/Install_Arch_Linux_on_a_USB_key#Installation_tweaks","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Wiki - Arch Linux on USB - Installation Tweaks"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/Installation_guide","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Wiki - Installation Guide"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://wiki.archlinux.org/index.php/GRUB#UEFI_systems","rel":["nofollow"]},"children":[{"type":"text","value":"Arch Linux Wiki - GRUB - UEFI Systems"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://www.vagrantup.com/docs/virtualbox/configuration.html#vboxmanage-customizations","rel":["nofollow"]},"children":[{"type":"text","value":"Vagrant VBoxManage Customizations "}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"create-an-arch-linux-virtual-machine-with-vagrant","depth":2,"text":"Create an Arch Linux Virtual Machine with Vagrant"},{"id":"install-arch-linux-on-the-usb-drive","depth":2,"text":"Install Arch Linux on the USB Drive","children":[{"id":"partition-the-disk-uefi-with-gpt","depth":3,"text":"Partition the Disk (UEFI with GPT)"},{"id":"format-the-partitions","depth":3,"text":"Format the Partitions"},{"id":"mount-the-partitions-and-bootstrap-the-environment","depth":3,"text":"Mount the Partitions and Bootstrap the Environment"},{"id":"configure-the-new-environment","depth":3,"text":"Configure the New Environment"}]},{"id":"side-note","depth":2,"text":"Side-note"},{"id":"references","depth":2,"text":"References"}]}},"_type":"markdown","_id":"content:articles:persistent-archlinux-usb.md","_source":"content","_file":"articles/persistent-archlinux-usb.md","_extension":"md"} \ No newline at end of file diff --git a/api/_content/query/6WfgQ5T9tH.1726174725311.json b/api/_content/query/1BkkvizQw8.1727638383380.json similarity index 99% rename from api/_content/query/6WfgQ5T9tH.1726174725311.json rename to api/_content/query/1BkkvizQw8.1727638383380.json index 16c4af21..c2772ab5 100644 --- a/api/_content/query/6WfgQ5T9tH.1726174725311.json +++ b/api/_content/query/1BkkvizQw8.1727638383380.json @@ -1 +1 @@ -{"_path":"/articles/doctl","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Exploring the Digital Ocean `doctl` Utility","description":"I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean doctl command line utility.\nThis proved to be an extremely easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future.","date":"2023-01-01","tags":["linux","digital-ocean"],"categories":["linux"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"doctl"}]},{"type":"text","value":" command line utility.\nThis proved to be an "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"extremely"}]},{"type":"text","value":" easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"doctl"}]},{"type":"text","value":" command line utility.\nThis proved to be an "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"extremely"}]},{"type":"text","value":" easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"To start things off, I had to install and setup authentication to Digital Ocean. Doing\nthis on my Mac machine, I opted to use "},{"type":"element","tag":"a","props":{"href":"https://brew.sh/","rel":["nofollow"]},"children":[{"type":"text","value":"Homebrew"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"# install `doctl`\nbrew install doctl\n\n# setup authentication\ndoctl auth init\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# install `doctl`\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"brew"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" doctl\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# setup authentication\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" auth"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" init\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"While the online "},{"type":"element","tag":"a","props":{"href":"https://docs.digitalocean.com/reference/doctl/reference/compute/droplet/create/","rel":["nofollow"]},"children":[{"type":"text","value":"documentation"}]},{"type":"text","value":" is fantastic, I instead found myself mostly referencing the outputs of "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--help"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute droplet create --help\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" droplet"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" create"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --help\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I had to find the image name of the version of Ubuntu I wanted to install:"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute image list --public | grep ubuntu-22\n\n# 118857366 22.04 (LTS) x64 snapshot Ubuntu ubuntu-22-04-x64 true 7\n# 119383150 22.10 x64 snapshot Ubuntu ubuntu-22-10-x64 true 7\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" image"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --public"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" |"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" grep"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ubuntu-22\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# 118857366 22.04 (LTS) x64 snapshot Ubuntu ubuntu-22-04-x64 true 7\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# 119383150 22.10 x64 snapshot Ubuntu ubuntu-22-10-x64 true 7\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And also the slug of the compute size:"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute size list\n\n# Slug Description Memory VCPUs Disk Price Monthly Price Hourly\n# s-1vcpu-512mb-10gb Basic 512 1 10 4.00 0.005950\n# s-1vcpu-1gb Basic 1024 1 25 6.00 0.008930\n# s-1vcpu-1gb-amd Basic AMD 1024 1 25 7.00 0.010420\n# s-1vcpu-1gb-intel Basic Intel 1024 1 25 7.00 0.010420\n# s-1vcpu-2gb Basic 2048 1 50 12.00 0.017860\n# s-1vcpu-2gb-amd Basic AMD 2048 1 50 14.00 0.020830\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" size"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# Slug Description Memory VCPUs Disk Price Monthly Price Hourly\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-512mb-10gb Basic 512 1 10 4.00 0.005950\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-1gb Basic 1024 1 25 6.00 0.008930\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-1gb-amd Basic AMD 1024 1 25 7.00 0.010420\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-1gb-intel Basic Intel 1024 1 25 7.00 0.010420\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-2gb Basic 2048 1 50 12.00 0.017860\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-2gb-amd Basic AMD 2048 1 50 14.00 0.020830\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I've also configured a few SSH keys with Digital Ocean, and I can have the key (specified by ID) provisioned to the machine using the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--ssh-keys"}]},{"type":"text","value":" flag."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute ssh-key list\n\n# ID Name FingerPrint\n# 1234 mini \n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ssh-key"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# ID Name FingerPrint\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# 1234 mini \n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Also, I wanted to install a few packages to the box upon creation, this can be done easily with the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--user-data-file"}]},{"type":"text","value":" flag to run an initialization script."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"echo 'apt install -y imagemagick zip' > bootstrap.sh\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"echo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 'apt install -y imagemagick zip'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" >"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" bootstrap.sh\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Putting it all together, here is the simple command for creating a small compute instance!"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute droplet create \\\n --image ubuntu-22-10-x64 \\\n --size s-1vcpu-512mb-10gb \\\n --region nyc1 \\\n --ssh-keys 1234 \\\n --user-data-file boostrap.sh \\\n ephemeral\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" droplet"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" create"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --image"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ubuntu-22-10-x64"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --size"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" s-1vcpu-512mb-10gb"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --region"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" nyc1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --ssh-keys"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1234"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --user-data-file"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" boostrap.sh"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ephemeral\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Finally, I can connect, do my thing, and destroy the instance."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute ssh ephemeral\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ssh"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ephemeral\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute droplet delete --force ephemeral\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" droplet"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" delete"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --force"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ephemeral\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"All-in-all, I was up and running in about 20 minutes. What a handy utility!"}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:doctl.md","_source":"content","_file":"articles/doctl.md","_stem":"articles/doctl","_extension":"md"} \ No newline at end of file +{"_path":"/articles/doctl","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Exploring the Digital Ocean `doctl` Utility","description":"I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean doctl command line utility.\nThis proved to be an extremely easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future.","date":"2023-01-01","tags":["linux","digital-ocean"],"categories":["linux"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"doctl"}]},{"type":"text","value":" command line utility.\nThis proved to be an "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"extremely"}]},{"type":"text","value":" easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"doctl"}]},{"type":"text","value":" command line utility.\nThis proved to be an "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"extremely"}]},{"type":"text","value":" easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"To start things off, I had to install and setup authentication to Digital Ocean. Doing\nthis on my Mac machine, I opted to use "},{"type":"element","tag":"a","props":{"href":"https://brew.sh/","rel":["nofollow"]},"children":[{"type":"text","value":"Homebrew"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"# install `doctl`\nbrew install doctl\n\n# setup authentication\ndoctl auth init\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# install `doctl`\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"brew"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" doctl\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# setup authentication\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" auth"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" init\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"While the online "},{"type":"element","tag":"a","props":{"href":"https://docs.digitalocean.com/reference/doctl/reference/compute/droplet/create/","rel":["nofollow"]},"children":[{"type":"text","value":"documentation"}]},{"type":"text","value":" is fantastic, I instead found myself mostly referencing the outputs of "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--help"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute droplet create --help\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" droplet"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" create"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --help\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I had to find the image name of the version of Ubuntu I wanted to install:"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute image list --public | grep ubuntu-22\n\n# 118857366 22.04 (LTS) x64 snapshot Ubuntu ubuntu-22-04-x64 true 7\n# 119383150 22.10 x64 snapshot Ubuntu ubuntu-22-10-x64 true 7\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" image"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --public"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" |"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" grep"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ubuntu-22\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# 118857366 22.04 (LTS) x64 snapshot Ubuntu ubuntu-22-04-x64 true 7\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# 119383150 22.10 x64 snapshot Ubuntu ubuntu-22-10-x64 true 7\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And also the slug of the compute size:"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute size list\n\n# Slug Description Memory VCPUs Disk Price Monthly Price Hourly\n# s-1vcpu-512mb-10gb Basic 512 1 10 4.00 0.005950\n# s-1vcpu-1gb Basic 1024 1 25 6.00 0.008930\n# s-1vcpu-1gb-amd Basic AMD 1024 1 25 7.00 0.010420\n# s-1vcpu-1gb-intel Basic Intel 1024 1 25 7.00 0.010420\n# s-1vcpu-2gb Basic 2048 1 50 12.00 0.017860\n# s-1vcpu-2gb-amd Basic AMD 2048 1 50 14.00 0.020830\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" size"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# Slug Description Memory VCPUs Disk Price Monthly Price Hourly\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-512mb-10gb Basic 512 1 10 4.00 0.005950\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-1gb Basic 1024 1 25 6.00 0.008930\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-1gb-amd Basic AMD 1024 1 25 7.00 0.010420\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-1gb-intel Basic Intel 1024 1 25 7.00 0.010420\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-2gb Basic 2048 1 50 12.00 0.017860\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# s-1vcpu-2gb-amd Basic AMD 2048 1 50 14.00 0.020830\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I've also configured a few SSH keys with Digital Ocean, and I can have the key (specified by ID) provisioned to the machine using the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--ssh-keys"}]},{"type":"text","value":" flag."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute ssh-key list\n\n# ID Name FingerPrint\n# 1234 mini \n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ssh-key"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# ID Name FingerPrint\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# 1234 mini \n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Also, I wanted to install a few packages to the box upon creation, this can be done easily with the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"--user-data-file"}]},{"type":"text","value":" flag to run an initialization script."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"echo 'apt install -y imagemagick zip' > bootstrap.sh\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"echo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 'apt install -y imagemagick zip'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" >"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" bootstrap.sh\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Putting it all together, here is the simple command for creating a small compute instance!"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute droplet create \\\n --image ubuntu-22-10-x64 \\\n --size s-1vcpu-512mb-10gb \\\n --region nyc1 \\\n --ssh-keys 1234 \\\n --user-data-file boostrap.sh \\\n ephemeral\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" droplet"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" create"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --image"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ubuntu-22-10-x64"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --size"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" s-1vcpu-512mb-10gb"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --region"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" nyc1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --ssh-keys"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1234"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --user-data-file"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" boostrap.sh"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ephemeral\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Finally, I can connect, do my thing, and destroy the instance."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute ssh ephemeral\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ssh"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ephemeral\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"doctl compute droplet delete --force ephemeral\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"doctl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" compute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" droplet"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" delete"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --force"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ephemeral\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"All-in-all, I was up and running in about 20 minutes. What a handy utility!"}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:doctl.md","_source":"content","_file":"articles/doctl.md","_extension":"md"} \ No newline at end of file diff --git a/api/_content/query/ZzD9WRl1Uk.1726174725311.json b/api/_content/query/AwYZnKuAHr.1727638383380.json similarity index 81% rename from api/_content/query/ZzD9WRl1Uk.1726174725311.json rename to api/_content/query/AwYZnKuAHr.1727638383380.json index 284f2adb..5852a0dd 100644 --- a/api/_content/query/ZzD9WRl1Uk.1726174725311.json +++ b/api/_content/query/AwYZnKuAHr.1727638383380.json @@ -1 +1 @@ -{"_path":"/articles/vim-fugitive-gpg-pinentry","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Using pinentry-mac to sign commits from vim-fugitive","description":"In order to sign git commits from within Vim using a plugin like tpope/vim-fugitive, it is necessary to configure the gpg-agent to use a GUI based pinentry-program.","draft":false,"date":"2024-05-11","tags":["vim","tip"],"categories":["tooling","tips"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In order to sign git commits from within Vim using a plugin like "},{"type":"element","tag":"a","props":{"href":"https://github.com/tpope/vim-fugitive","rel":["nofollow"]},"children":[{"type":"text","value":"tpope/vim-fugitive"}]},{"type":"text","value":", it is necessary to configure the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"gpg-agent"}]},{"type":"text","value":" to use a GUI based "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-program"}]},{"type":"text","value":"."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In order to sign git commits from within Vim using a plugin like "},{"type":"element","tag":"a","props":{"href":"https://github.com/tpope/vim-fugitive","rel":["nofollow"]},"children":[{"type":"text","value":"tpope/vim-fugitive"}]},{"type":"text","value":", it is necessary to configure the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"gpg-agent"}]},{"type":"text","value":" to use a GUI based "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-program"}]},{"type":"text","value":"."}]},{"type":"element","tag":"h2","props":{"id":"preface"},"children":[{"type":"text","value":"Preface"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The man, the myth, the legend, Timothy Popallopollis himself "},{"type":"element","tag":"a","props":{"href":"https://github.com/tpope/vim-fugitive/issues/846#issuecomment-253816577","rel":["nofollow"]},"children":[{"type":"text","value":"recommends"}]},{"type":"text","value":" configuring your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"gpg-agent"}]},{"type":"text","value":" to use a GUI based "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-program"}]},{"type":"text","value":". On macOS this can be done quite by simply installing "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-mac"}]},{"type":"text","value":", and updating your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"gpg-agent.conf"}]},{"type":"text","value":"."}]},{"type":"element","tag":"h2","props":{"id":"configuration"},"children":[{"type":"text","value":"Configuration"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First things first, let's install the pinentry program."}]},{"type":"element","tag":"pre","props":{"code":"$ brew install pinentry-mac\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" brew"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pinentry-mac\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, all we need to do is set the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-program"}]},{"type":"text","value":" option in your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"~/.gnupg/gpg-agent.conf"}]},{"type":"text","value":" file."}]},{"type":"element","tag":"pre","props":{"code":"default-cache-ttl 600\nmax-cache-ttl 7200\npinentry-program /opt/homebrew/bin/pinentry-mac\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"default-cache-ttl 600\nmax-cache-ttl 7200\npinentry-program /opt/homebrew/bin/pinentry-mac\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If your don't know the path to your pinentry program, you can throw down a quick "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"which"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"code":"$ which pinentry-mac\n/opt/homebrew/bin/pinentry-mac\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" which"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pinentry-mac\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"/opt/homebrew/bin/pinentry-mac\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Or use your Homebrew prefix."}]},{"type":"element","tag":"pre","props":{"code":"$ echo $(brew --prefix)/bin/pinentry-mac\n/opt/homebrew/bin/pinentry-mac\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" echo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" $("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"brew"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --prefix"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"/bin/pinentry-mac\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"/opt/homebrew/bin/pinentry-mac\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"But that's all it takes. Now, you should be prompted to enter your gpg pin in an external window when signing commits from vim."}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"preface","depth":2,"text":"Preface"},{"id":"configuration","depth":2,"text":"Configuration"}]}},"_type":"markdown","_id":"content:articles:vim-fugitive-gpg-pinentry.md","_source":"content","_file":"articles/vim-fugitive-gpg-pinentry.md","_stem":"articles/vim-fugitive-gpg-pinentry","_extension":"md"} \ No newline at end of file +{"_path":"/articles/vim-fugitive-gpg-pinentry","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Using pinentry-mac to sign commits from vim-fugitive","description":"In order to sign git commits from within Vim using a plugin like tpope/vim-fugitive, it is necessary to configure the gpg-agent to use a GUI based pinentry-program.","draft":false,"date":"2024-05-11","tags":["vim","tip"],"categories":["tooling","tips"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In order to sign git commits from within Vim using a plugin like "},{"type":"element","tag":"a","props":{"href":"https://github.com/tpope/vim-fugitive","rel":["nofollow"]},"children":[{"type":"text","value":"tpope/vim-fugitive"}]},{"type":"text","value":", it is necessary to configure the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"gpg-agent"}]},{"type":"text","value":" to use a GUI based "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-program"}]},{"type":"text","value":"."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In order to sign git commits from within Vim using a plugin like "},{"type":"element","tag":"a","props":{"href":"https://github.com/tpope/vim-fugitive","rel":["nofollow"]},"children":[{"type":"text","value":"tpope/vim-fugitive"}]},{"type":"text","value":", it is necessary to configure the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"gpg-agent"}]},{"type":"text","value":" to use a GUI based "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-program"}]},{"type":"text","value":"."}]},{"type":"element","tag":"h2","props":{"id":"preface"},"children":[{"type":"text","value":"Preface"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The man, the myth, the legend, Timothy Popallopollis himself "},{"type":"element","tag":"a","props":{"href":"https://github.com/tpope/vim-fugitive/issues/846#issuecomment-253816577","rel":["nofollow"]},"children":[{"type":"text","value":"recommends"}]},{"type":"text","value":" configuring your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"gpg-agent"}]},{"type":"text","value":" to use a GUI based "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-program"}]},{"type":"text","value":". On macOS this can be done quite by simply installing "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-mac"}]},{"type":"text","value":", and updating your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"gpg-agent.conf"}]},{"type":"text","value":"."}]},{"type":"element","tag":"h2","props":{"id":"configuration"},"children":[{"type":"text","value":"Configuration"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First things first, let's install the pinentry program."}]},{"type":"element","tag":"pre","props":{"code":"$ brew install pinentry-mac\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" brew"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pinentry-mac\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, all we need to do is set the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"pinentry-program"}]},{"type":"text","value":" option in your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"~/.gnupg/gpg-agent.conf"}]},{"type":"text","value":" file."}]},{"type":"element","tag":"pre","props":{"code":"default-cache-ttl 600\nmax-cache-ttl 7200\npinentry-program /opt/homebrew/bin/pinentry-mac\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"default-cache-ttl 600\nmax-cache-ttl 7200\npinentry-program /opt/homebrew/bin/pinentry-mac\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If your don't know the path to your pinentry program, you can throw down a quick "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"which"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"code":"$ which pinentry-mac\n/opt/homebrew/bin/pinentry-mac\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" which"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pinentry-mac\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"/opt/homebrew/bin/pinentry-mac\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Or use your Homebrew prefix."}]},{"type":"element","tag":"pre","props":{"code":"$ echo $(brew --prefix)/bin/pinentry-mac\n/opt/homebrew/bin/pinentry-mac\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" echo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" $("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"brew"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --prefix"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":")/bin/pinentry-mac\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"/opt/homebrew/bin/pinentry-mac\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"But that's all it takes. Now, you should be prompted to enter your gpg pin in an external window when signing commits from vim."}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"preface","depth":2,"text":"Preface"},{"id":"configuration","depth":2,"text":"Configuration"}]}},"_type":"markdown","_id":"content:articles:vim-fugitive-gpg-pinentry.md","_source":"content","_file":"articles/vim-fugitive-gpg-pinentry.md","_extension":"md"} \ No newline at end of file diff --git a/api/_content/query/Nr5UObwduV.1726174725311.json b/api/_content/query/C0SimRluqy.1727638383380.json similarity index 98% rename from api/_content/query/Nr5UObwduV.1726174725311.json rename to api/_content/query/C0SimRluqy.1727638383380.json index 178e1f2b..d88738ad 100644 --- a/api/_content/query/Nr5UObwduV.1726174725311.json +++ b/api/_content/query/C0SimRluqy.1727638383380.json @@ -1 +1 @@ -{"_path":"/articles/nuxt-v3-migration","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"This Website Has Been Migrated to Nuxt 3 🎉","description":"This website has been migrated to the latest version of the Nuxt web framework, and with it comes all of the exciting goodies that the Vue and Nuxt teams have been concocting over the past few years.\nNot to mention, all of the great plugins in the Vue ecosystem!","date":"2022-12-31","tags":["nuxt"],"categories":["web"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This website has been migrated to the latest version of the Nuxt web framework, and with it comes all of the exciting goodies that the Vue and Nuxt teams have been concocting over the past few years.\nNot to mention, all of the great plugins in the Vue ecosystem!"}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This website has been migrated to the latest version of the Nuxt web framework, and with it comes all of the exciting goodies that the Vue and Nuxt teams have been concocting over the past few years.\nNot to mention, all of the great plugins in the Vue ecosystem!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you're curious what changes were required to make the migration, you can check out "},{"type":"element","tag":"a","props":{"href":"https://github.com/cmpadden/cmpadden.github.io/pull/3","rel":["nofollow"]},"children":[{"type":"text","value":"pull request #3"}]},{"type":"text","value":" in the GitHub repository."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"img","props":{"alt":"Screenshot of Nuxt Migration Pull Request","src":"/images/nuxt-migration-pr.png"},"children":[]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"While the documentation for making this migration is great, there were many breaking changes, and the overall process was quite tedious.\nFor this reason, I opted to generate a new project entirely, and port existing code to this clean slate.\nI believe that this resulted in a project with a bit less cruft."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The most valuable resources for making these changes include:"}]},{"type":"element","tag":"ul","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://nuxt.com/docs/migration/overview","rel":["nofollow"]},"children":[{"type":"text","value":"The Nuxt Migration Guide"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://nuxt.com/docs/getting-started/introduction","rel":["nofollow"]},"children":[{"type":"text","value":"The Nuxt Framework Guide"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://tailwindcss.nuxt.dev/","rel":["nofollow"]},"children":[{"type":"text","value":"Nuxt Tailwind Module Documentation"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://content.nuxtjs.org/","rel":["nofollow"]},"children":[{"type":"text","value":"Nuxt Content Module Documentation"}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Part of the delay for doing this upgrade was in waiting for module developers to support this major release.\nI'm super thankful for all of the hard work they've don, and I'm excited to explore all of the new features available!\nI just hope that the breaking changes in this release don't cause too much fracturing of the community, as it does feel like déjà vu of Python 2 and 3."}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:nuxt-v3-migration.md","_source":"content","_file":"articles/nuxt-v3-migration.md","_stem":"articles/nuxt-v3-migration","_extension":"md"} \ No newline at end of file +{"_path":"/articles/nuxt-v3-migration","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"This Website Has Been Migrated to Nuxt 3 🎉","description":"This website has been migrated to the latest version of the Nuxt web framework, and with it comes all of the exciting goodies that the Vue and Nuxt teams have been concocting over the past few years.\nNot to mention, all of the great plugins in the Vue ecosystem!","date":"2022-12-31","tags":["nuxt"],"categories":["web"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This website has been migrated to the latest version of the Nuxt web framework, and with it comes all of the exciting goodies that the Vue and Nuxt teams have been concocting over the past few years.\nNot to mention, all of the great plugins in the Vue ecosystem!"}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This website has been migrated to the latest version of the Nuxt web framework, and with it comes all of the exciting goodies that the Vue and Nuxt teams have been concocting over the past few years.\nNot to mention, all of the great plugins in the Vue ecosystem!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you're curious what changes were required to make the migration, you can check out "},{"type":"element","tag":"a","props":{"href":"https://github.com/cmpadden/cmpadden.github.io/pull/3","rel":["nofollow"]},"children":[{"type":"text","value":"pull request #3"}]},{"type":"text","value":" in the GitHub repository."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"img","props":{"alt":"Screenshot of Nuxt Migration Pull Request","src":"/images/nuxt-migration-pr.png"},"children":[]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"While the documentation for making this migration is great, there were many breaking changes, and the overall process was quite tedious.\nFor this reason, I opted to generate a new project entirely, and port existing code to this clean slate.\nI believe that this resulted in a project with a bit less cruft."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The most valuable resources for making these changes include:"}]},{"type":"element","tag":"ul","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://nuxt.com/docs/migration/overview","rel":["nofollow"]},"children":[{"type":"text","value":"The Nuxt Migration Guide"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://nuxt.com/docs/getting-started/introduction","rel":["nofollow"]},"children":[{"type":"text","value":"The Nuxt Framework Guide"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://tailwindcss.nuxt.dev/","rel":["nofollow"]},"children":[{"type":"text","value":"Nuxt Tailwind Module Documentation"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://content.nuxtjs.org/","rel":["nofollow"]},"children":[{"type":"text","value":"Nuxt Content Module Documentation"}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Part of the delay for doing this upgrade was in waiting for module developers to support this major release.\nI'm super thankful for all of the hard work they've don, and I'm excited to explore all of the new features available!\nI just hope that the breaking changes in this release don't cause too much fracturing of the community, as it does feel like déjà vu of Python 2 and 3."}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:nuxt-v3-migration.md","_source":"content","_file":"articles/nuxt-v3-migration.md","_extension":"md"} \ No newline at end of file diff --git a/api/_content/query/DIau8q3IMV.1726174725311.json b/api/_content/query/DIau8q3IMV.1727638383380.json similarity index 100% rename from api/_content/query/DIau8q3IMV.1726174725311.json rename to api/_content/query/DIau8q3IMV.1727638383380.json diff --git a/api/_content/query/tGrf8kFZOz.1726174725311.json b/api/_content/query/PYi9meWOqm.1727638383380.json similarity index 98% rename from api/_content/query/tGrf8kFZOz.1726174725311.json rename to api/_content/query/PYi9meWOqm.1727638383380.json index 0c365c45..73087874 100644 --- a/api/_content/query/tGrf8kFZOz.1726174725311.json +++ b/api/_content/query/PYi9meWOqm.1727638383380.json @@ -1 +1 @@ -{"_path":"/articles/apu2-firmware-upgrade","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Upgrading the Firmware on the PCEngines APU2","description":"I've had a PCEngines APU2 gathering dust for a\nfew years, and have recently decided to dust it off.","date":"2019-12-21","draft":false,"tags":["pcengine","apu"],"categories":["linux"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I've had a "},{"type":"element","tag":"a","props":{"href":"https://pcengines.ch/apu2.htm","rel":["nofollow"]},"children":[{"type":"text","value":"PCEngines APU2"}]},{"type":"text","value":" gathering dust for a\nfew years, and have recently decided to dust it off."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Since the last time the device has been powered on, there have been many great\nimprovements to the firmware, and it was very-much due for an upgrade. The\nfollowing steps outline how the firmware was upgraded on the APU from the\nalready-installed operating system -- CentOS."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I've had a "},{"type":"element","tag":"a","props":{"href":"https://pcengines.ch/apu2.htm","rel":["nofollow"]},"children":[{"type":"text","value":"PCEngines APU2"}]},{"type":"text","value":" gathering dust for a\nfew years, and have recently decided to dust it off."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Since the last time the device has been powered on, there have been many great\nimprovements to the firmware, and it was very-much due for an upgrade. The\nfollowing steps outline how the firmware was upgraded on the APU from the\nalready-installed operating system -- CentOS."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, we will connect to the device over the serial port"}]},{"type":"element","tag":"pre","props":{"code":"screen /dev/tty.usbserial 115200\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"screen /dev/tty.usbserial 115200\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, we will install the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"flashrom"}]},{"type":"text","value":" utility that is needed to update the\nfirmware. Because it is not available in the default "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"yum"}]},{"type":"text","value":" repositories, we\nwill enable the "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Extra Packages for Enterprise Linux"}]},{"type":"text","value":" (EPEL) repository before\ninstallation."}]},{"type":"element","tag":"pre","props":{"code":"sudo yum install epel-release\nsudo yum install flashrom\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" yum"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" epel-release\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" yum"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" flashrom\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Next, we will download the latest version of the firmware that is compatible\nwith the APU2 device from the PC Engines release website:\n"},{"type":"element","tag":"a","props":{"href":"https://pcengines.github.io/","rel":["nofollow"]},"children":[{"type":"text","value":"https://pcengines.github.io/"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"code":"curl -O https://3mdeb.com/open-source-firmware/pcengines/apu2/apu2_v4.11.0.1.rom\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"curl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -O"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" https://3mdeb.com/open-source-firmware/pcengines/apu2/apu2_v4.11.0.1.rom\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And finally, we will flash the firmware..."}]},{"type":"element","tag":"pre","props":{"code":"sudo flashrom -w apu2_v4.11.0.1.rom -p internal:boardmismatch=force\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" flashrom"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -w"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" apu2_v4.11.0.1.rom"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -p"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" internal:boardmismatch=force\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"strong","props":{},"children":[{"type":"text","value":"References:"}]}]},{"type":"element","tag":"ul","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://pcengines.ch/apu2.htm","rel":["nofollow"]},"children":[{"type":"text","value":"https://pcengines.ch/apu2.htm"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://pcengines.github.io/","rel":["nofollow"]},"children":[{"type":"text","value":"https://pcengines.github.io/"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/pcengines/apu2-documentation/blob/master/docs/firmware_flashing.md","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/pcengines/apu2-documentation/blob/master/docs/firmware_flashing.md"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/pcengines/apu2-documentation/blob/master/docs/cold_reset.md","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/pcengines/apu2-documentation/blob/master/docs/cold_reset.md"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/elad/openbsd-apu2","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/elad/openbsd-apu2"}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:apu2-firmware-upgrade.md","_source":"content","_file":"articles/apu2-firmware-upgrade.md","_stem":"articles/apu2-firmware-upgrade","_extension":"md"} \ No newline at end of file +{"_path":"/articles/apu2-firmware-upgrade","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Upgrading the Firmware on the PCEngines APU2","description":"I've had a PCEngines APU2 gathering dust for a\nfew years, and have recently decided to dust it off.","date":"2019-12-21","draft":false,"tags":["pcengine","apu"],"categories":["linux"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I've had a "},{"type":"element","tag":"a","props":{"href":"https://pcengines.ch/apu2.htm","rel":["nofollow"]},"children":[{"type":"text","value":"PCEngines APU2"}]},{"type":"text","value":" gathering dust for a\nfew years, and have recently decided to dust it off."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Since the last time the device has been powered on, there have been many great\nimprovements to the firmware, and it was very-much due for an upgrade. The\nfollowing steps outline how the firmware was upgraded on the APU from the\nalready-installed operating system -- CentOS."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"I've had a "},{"type":"element","tag":"a","props":{"href":"https://pcengines.ch/apu2.htm","rel":["nofollow"]},"children":[{"type":"text","value":"PCEngines APU2"}]},{"type":"text","value":" gathering dust for a\nfew years, and have recently decided to dust it off."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Since the last time the device has been powered on, there have been many great\nimprovements to the firmware, and it was very-much due for an upgrade. The\nfollowing steps outline how the firmware was upgraded on the APU from the\nalready-installed operating system -- CentOS."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, we will connect to the device over the serial port"}]},{"type":"element","tag":"pre","props":{"code":"screen /dev/tty.usbserial 115200\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"screen /dev/tty.usbserial 115200\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, we will install the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"flashrom"}]},{"type":"text","value":" utility that is needed to update the\nfirmware. Because it is not available in the default "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"yum"}]},{"type":"text","value":" repositories, we\nwill enable the "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Extra Packages for Enterprise Linux"}]},{"type":"text","value":" (EPEL) repository before\ninstallation."}]},{"type":"element","tag":"pre","props":{"code":"sudo yum install epel-release\nsudo yum install flashrom\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" yum"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" epel-release\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" yum"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" flashrom\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Next, we will download the latest version of the firmware that is compatible\nwith the APU2 device from the PC Engines release website:\n"},{"type":"element","tag":"a","props":{"href":"https://pcengines.github.io/","rel":["nofollow"]},"children":[{"type":"text","value":"https://pcengines.github.io/"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"code":"curl -O https://3mdeb.com/open-source-firmware/pcengines/apu2/apu2_v4.11.0.1.rom\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"curl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -O"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" https://3mdeb.com/open-source-firmware/pcengines/apu2/apu2_v4.11.0.1.rom\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And finally, we will flash the firmware..."}]},{"type":"element","tag":"pre","props":{"code":"sudo flashrom -w apu2_v4.11.0.1.rom -p internal:boardmismatch=force\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" flashrom"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -w"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" apu2_v4.11.0.1.rom"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -p"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" internal:boardmismatch=force\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"strong","props":{},"children":[{"type":"text","value":"References:"}]}]},{"type":"element","tag":"ul","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://pcengines.ch/apu2.htm","rel":["nofollow"]},"children":[{"type":"text","value":"https://pcengines.ch/apu2.htm"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://pcengines.github.io/","rel":["nofollow"]},"children":[{"type":"text","value":"https://pcengines.github.io/"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/pcengines/apu2-documentation/blob/master/docs/firmware_flashing.md","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/pcengines/apu2-documentation/blob/master/docs/firmware_flashing.md"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/pcengines/apu2-documentation/blob/master/docs/cold_reset.md","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/pcengines/apu2-documentation/blob/master/docs/cold_reset.md"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/elad/openbsd-apu2","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/elad/openbsd-apu2"}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:apu2-firmware-upgrade.md","_source":"content","_file":"articles/apu2-firmware-upgrade.md","_extension":"md"} \ No newline at end of file diff --git a/api/_content/query/pfbAdBSC9a.1726174725311.json b/api/_content/query/QB64GpMlA8.1727638383380.json similarity index 99% rename from api/_content/query/pfbAdBSC9a.1726174725311.json rename to api/_content/query/QB64GpMlA8.1727638383380.json index 6934c084..74ee3769 100644 --- a/api/_content/query/pfbAdBSC9a.1726174725311.json +++ b/api/_content/query/QB64GpMlA8.1727638383380.json @@ -1 +1 @@ -{"_path":"/articles/ssh-ed25519-sk-yubikey","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Configuring a YubiKey for use with OpenSSH","description":"YubiKey's are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" ed25519-sk key type that supports FIDO compliant hardware keys.","draft":false,"date":"2024-06-09","tags":["unix","configurations"],"categories":["tooling","tips"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://www.yubico.com/","rel":["nofollow"]},"children":[{"type":"text","value":"YubiKey's"}]},{"type":"text","value":" are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ed25519-sk"}]},{"type":"text","value":" key type that supports FIDO compliant hardware keys."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://www.yubico.com/","rel":["nofollow"]},"children":[{"type":"text","value":"YubiKey's"}]},{"type":"text","value":" are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ed25519-sk"}]},{"type":"text","value":" key type that supports FIDO compliant hardware keys."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In "},{"type":"element","tag":"a","props":{"href":"https://www.openssh.com/txt/release-8.2","rel":["nofollow"]},"children":[{"type":"text","value":"release 8.2 of OpenSSH"}]},{"type":"text","value":" support for FIDO devices was added with public key types \"ecdsa-sk\" and \"ed25519-sk\" (-sk standing for \"security key\"). This key type is supported by YubiKey's with firmware version 5.2.3 or higher."}]},{"type":"element","tag":"blockquote","props":{},"children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This release adds support for FIDO/U2F hardware authenticators to OpenSSH. U2F/FIDO are open standards for inexpensive two-factor authentication hardware that are widely used for website authentication. In OpenSSH FIDO devices are supported by new public key types \"ecdsa-sk\" and \"ed25519-sk\", along with corresponding certificate types."}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Let's get started by installing the latest version of OpenSSH via "},{"type":"element","tag":"a","props":{"href":"https://brew.sh/","rel":["nofollow"]},"children":[{"type":"text","value":"Homebrew"}]},{"type":"text","value":", along with the YubiKey Manager (ykman) CLI. The version of OpenSSH included with macOS is not compatible."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"$ brew install openssh ykman\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" brew"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" openssh"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ykman\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, let's confirm that our YubiKey has a firmware that is greater than 5.2.3:"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"$ ykman list\nYubiKey 5Ci (5.4.3) [OTP+FIDO+CCID]\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ykman"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"YubiKey"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 5Ci"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (5.4.3) [OTP+FIDO+CCID]\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Next, we'll go ahead and enable a pin on our device via the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"change-pin"}]},{"type":"text","value":" command, as this a requirement for our use."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"$ ykman fido access change-pin\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ykman"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" fido"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" access"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" change-pin\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And last, we'll generate the key on our device!"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"$ ssh-keygen -t ed25519-sk -O resident\nGenerating public/private ed25519-sk key pair.\nYou may need to touch your authenticator to authorize key generation.\n...\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ssh-keygen"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -t"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ed25519-sk"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -O"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" resident\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"Generating"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" public/private"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ed25519-sk"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" key"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pair.\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"You"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" may"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" need"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" to"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" touch"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" your"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" authenticator"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" to"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" authorize"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" key"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" generation.\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"...\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"We specify "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"resident"}]},{"type":"text","value":" to indicate that the key handle is to be stored on the YubiKey itself, since we will be using this device with multiple computers."}]},{"type":"element","tag":"pre","props":{"className":"language-txt shiki shiki-themes github-light","code":"resident\n Indicate that the key handle should be stored on the FIDO\n authenticator itself. This makes it easier to use the\n authenticator on multiple computers. Resident keys may be\n supported on FIDO2 authenticators and typically require that a PIN\n be set on the authenticator prior to generation. Resident keys\n may be loaded off the authenticator using ssh-add(1). Storing\n both parts of a key on a FIDO authenticator increases the\n likelihood of an attacker being able to use a stolen authenticator\n device.\n","language":"txt","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"resident\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" Indicate that the key handle should be stored on the FIDO\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" authenticator itself. This makes it easier to use the\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" authenticator on multiple computers. Resident keys may be\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" supported on FIDO2 authenticators and typically require that a PIN\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" be set on the authenticator prior to generation. Resident keys\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" may be loaded off the authenticator using ssh-add(1). Storing\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" both parts of a key on a FIDO authenticator increases the\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" likelihood of an attacker being able to use a stolen authenticator\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" device.\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And that's all it takes -- simple enough. Now, when interacting with "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"ssh"}]},{"type":"text","value":" or "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"git"}]},{"type":"text","value":" you will be prompted to touch the YubiKey to bring that little bit of physical 2FA."}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:ssh-ed25519-sk-yubikey.md","_source":"content","_file":"articles/ssh-ed25519-sk-yubikey.md","_stem":"articles/ssh-ed25519-sk-yubikey","_extension":"md"} \ No newline at end of file +{"_path":"/articles/ssh-ed25519-sk-yubikey","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Configuring a YubiKey for use with OpenSSH","description":"YubiKey's are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" ed25519-sk key type that supports FIDO compliant hardware keys.","draft":false,"date":"2024-06-09","tags":["unix","configurations"],"categories":["tooling","tips"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://www.yubico.com/","rel":["nofollow"]},"children":[{"type":"text","value":"YubiKey's"}]},{"type":"text","value":" are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ed25519-sk"}]},{"type":"text","value":" key type that supports FIDO compliant hardware keys."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://www.yubico.com/","rel":["nofollow"]},"children":[{"type":"text","value":"YubiKey's"}]},{"type":"text","value":" are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ed25519-sk"}]},{"type":"text","value":" key type that supports FIDO compliant hardware keys."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In "},{"type":"element","tag":"a","props":{"href":"https://www.openssh.com/txt/release-8.2","rel":["nofollow"]},"children":[{"type":"text","value":"release 8.2 of OpenSSH"}]},{"type":"text","value":" support for FIDO devices was added with public key types \"ecdsa-sk\" and \"ed25519-sk\" (-sk standing for \"security key\"). This key type is supported by YubiKey's with firmware version 5.2.3 or higher."}]},{"type":"element","tag":"blockquote","props":{},"children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This release adds support for FIDO/U2F hardware authenticators to OpenSSH. U2F/FIDO are open standards for inexpensive two-factor authentication hardware that are widely used for website authentication. In OpenSSH FIDO devices are supported by new public key types \"ecdsa-sk\" and \"ed25519-sk\", along with corresponding certificate types."}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Let's get started by installing the latest version of OpenSSH via "},{"type":"element","tag":"a","props":{"href":"https://brew.sh/","rel":["nofollow"]},"children":[{"type":"text","value":"Homebrew"}]},{"type":"text","value":", along with the YubiKey Manager (ykman) CLI. The version of OpenSSH included with macOS is not compatible."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"$ brew install openssh ykman\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" brew"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" install"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" openssh"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ykman\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, let's confirm that our YubiKey has a firmware that is greater than 5.2.3:"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"$ ykman list\nYubiKey 5Ci (5.4.3) [OTP+FIDO+CCID]\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ykman"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" list\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"YubiKey"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 5Ci"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (5.4.3) [OTP+FIDO+CCID]\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Next, we'll go ahead and enable a pin on our device via the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"change-pin"}]},{"type":"text","value":" command, as this a requirement for our use."}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"$ ykman fido access change-pin\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ykman"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" fido"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" access"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" change-pin\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And last, we'll generate the key on our device!"}]},{"type":"element","tag":"pre","props":{"className":"language-sh shiki shiki-themes github-light","code":"$ ssh-keygen -t ed25519-sk -O resident\nGenerating public/private ed25519-sk key pair.\nYou may need to touch your authenticator to authorize key generation.\n...\n","language":"sh","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ssh-keygen"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -t"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ed25519-sk"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -O"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" resident\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"Generating"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" public/private"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ed25519-sk"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" key"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pair.\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"You"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" may"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" need"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" to"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" touch"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" your"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" authenticator"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" to"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" authorize"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" key"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" generation.\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"...\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"We specify "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"resident"}]},{"type":"text","value":" to indicate that the key handle is to be stored on the YubiKey itself, since we will be using this device with multiple computers."}]},{"type":"element","tag":"pre","props":{"className":"language-txt shiki shiki-themes github-light","code":"resident\n Indicate that the key handle should be stored on the FIDO\n authenticator itself. This makes it easier to use the\n authenticator on multiple computers. Resident keys may be\n supported on FIDO2 authenticators and typically require that a PIN\n be set on the authenticator prior to generation. Resident keys\n may be loaded off the authenticator using ssh-add(1). Storing\n both parts of a key on a FIDO authenticator increases the\n likelihood of an attacker being able to use a stolen authenticator\n device.\n","language":"txt","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"resident\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" Indicate that the key handle should be stored on the FIDO\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" authenticator itself. This makes it easier to use the\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" authenticator on multiple computers. Resident keys may be\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" supported on FIDO2 authenticators and typically require that a PIN\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" be set on the authenticator prior to generation. Resident keys\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" may be loaded off the authenticator using ssh-add(1). Storing\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" both parts of a key on a FIDO authenticator increases the\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" likelihood of an attacker being able to use a stolen authenticator\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":" device.\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And that's all it takes -- simple enough. Now, when interacting with "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"ssh"}]},{"type":"text","value":" or "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"git"}]},{"type":"text","value":" you will be prompted to touch the YubiKey to bring that little bit of physical 2FA."}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:ssh-ed25519-sk-yubikey.md","_source":"content","_file":"articles/ssh-ed25519-sk-yubikey.md","_extension":"md"} \ No newline at end of file diff --git a/api/_content/query/TDaCLaQ73L.1726174725311.json b/api/_content/query/SFFy74pu72.1727638383380.json similarity index 98% rename from api/_content/query/TDaCLaQ73L.1726174725311.json rename to api/_content/query/SFFy74pu72.1727638383380.json index cf77636a..a9d5401c 100644 --- a/api/_content/query/TDaCLaQ73L.1726174725311.json +++ b/api/_content/query/SFFy74pu72.1727638383380.json @@ -1 +1 @@ -{"_path":"/articles/reset-ipmi-password-from-host-os","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Reset IPMI Credentials from the Host OS","description":"If you ever find yourself locked out of the Intelligent Platform Management Interface (IPMI) of a server, these\ninstructions will guide your through the process of resetting the credentials to their default values from the host\noperating system.","date":"2021-12-27","tags":["homelab","supermicro","truenas"],"categories":["homelab"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you ever find yourself locked out of the Intelligent Platform Management Interface (IPMI) of a server, these\ninstructions will guide your through the process of resetting the credentials to their default values from the host\noperating system."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you ever find yourself locked out of the Intelligent Platform Management Interface (IPMI) of a server, these\ninstructions will guide your through the process of resetting the credentials to their default values from the host\noperating system."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you are using an operating system like TrueNAS -- good news! It's possible to reset the IPMI password directly from\nthe web interface. This is done by navigating to "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Network > IPMI"}]},{"type":"text","value":", and simply entering a new value in the "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"IPMI\nPassword Reset"}]},{"type":"text","value":" field."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you are using some other OS that doesn't have this feature, you can achieve similar results by using the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ipmitool"}]},{"type":"text","value":"\ncommand-line utility."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, you'll want to determine the user ID associated with the user for whom you'd like to reset the password."}]},{"type":"element","tag":"pre","props":{"code":"# ipmitool user list\nID Name Callin Link Auth IPMI Msg Channel Priv Limit\n1 true false false Unknown (0x00)\n2 ADMIN true false false Unknown (0x00)\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"# ipmitool user list\nID Name Callin Link Auth IPMI Msg Channel Priv Limit\n1 true false false Unknown (0x00)\n2 ADMIN true false false Unknown (0x00)\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In this case, we will be resetting the password for "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"ADMIN"}]},{"type":"text","value":" who has a user ID of "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"2"}]},{"type":"text","value":". Then we'll assign the new\npassword like so:"}]},{"type":"element","tag":"pre","props":{"code":"# ipmitool user set password 2 \n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"# ipmitool user set password 2 \n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And you should be good to go!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"..."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Alternatively, if you'd like to factory reset the baseboard management controller (BMC), which will reset the IPMI\ncredentials to their default value, you can issue the following command."}]},{"type":"element","tag":"pre","props":{"code":"# ipmitool raw 0x3c 0x40\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"# ipmitool raw 0x3c 0x40\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Where "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"0x3c"}]},{"type":"text","value":" is the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":""}]},{"type":"text","value":" argument, a.k.a. the network function code that defines the functional routing for\nmessages, and "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"0x40"}]},{"type":"text","value":" is the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":""}]},{"type":"text","value":". According to section 5.1 of the "},{"type":"element","tag":"a","props":{"href":"https://www.intel.com/content/dam/www/public/us/en/documents/product-briefs/ipmi-second-gen-interface-spec-v2-rev1-1.pdf","rel":["nofollow"]},"children":[{"type":"text","value":"IPMI interface\nspecification"}]},{"type":"text","value":",\n"},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"netfn"}]},{"type":"text","value":" codes ranging from 0x30 to 0x3F are reserved for vendor specific functions. I searched around for some\nSupermicro references on these vendor specific network functions without much luck other than various "},{"type":"element","tag":"a","props":{"href":"https://www.supermicro.com/support/faqs/faq.cfm?faq=15448","rel":["nofollow"]},"children":[{"type":"text","value":"support\nresponses"}]},{"type":"text","value":" on how to reset a device. Bummer!"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:reset-ipmi-password-from-host-os.md","_source":"content","_file":"articles/reset-ipmi-password-from-host-os.md","_stem":"articles/reset-ipmi-password-from-host-os","_extension":"md"} \ No newline at end of file +{"_path":"/articles/reset-ipmi-password-from-host-os","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Reset IPMI Credentials from the Host OS","description":"If you ever find yourself locked out of the Intelligent Platform Management Interface (IPMI) of a server, these\ninstructions will guide your through the process of resetting the credentials to their default values from the host\noperating system.","date":"2021-12-27","tags":["homelab","supermicro","truenas"],"categories":["homelab"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you ever find yourself locked out of the Intelligent Platform Management Interface (IPMI) of a server, these\ninstructions will guide your through the process of resetting the credentials to their default values from the host\noperating system."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you ever find yourself locked out of the Intelligent Platform Management Interface (IPMI) of a server, these\ninstructions will guide your through the process of resetting the credentials to their default values from the host\noperating system."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you are using an operating system like TrueNAS -- good news! It's possible to reset the IPMI password directly from\nthe web interface. This is done by navigating to "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Network > IPMI"}]},{"type":"text","value":", and simply entering a new value in the "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"IPMI\nPassword Reset"}]},{"type":"text","value":" field."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you are using some other OS that doesn't have this feature, you can achieve similar results by using the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"ipmitool"}]},{"type":"text","value":"\ncommand-line utility."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, you'll want to determine the user ID associated with the user for whom you'd like to reset the password."}]},{"type":"element","tag":"pre","props":{"code":"# ipmitool user list\nID Name Callin Link Auth IPMI Msg Channel Priv Limit\n1 true false false Unknown (0x00)\n2 ADMIN true false false Unknown (0x00)\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"# ipmitool user list\nID Name Callin Link Auth IPMI Msg Channel Priv Limit\n1 true false false Unknown (0x00)\n2 ADMIN true false false Unknown (0x00)\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In this case, we will be resetting the password for "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"ADMIN"}]},{"type":"text","value":" who has a user ID of "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"2"}]},{"type":"text","value":". Then we'll assign the new\npassword like so:"}]},{"type":"element","tag":"pre","props":{"code":"# ipmitool user set password 2 \n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"# ipmitool user set password 2 \n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And you should be good to go!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"..."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Alternatively, if you'd like to factory reset the baseboard management controller (BMC), which will reset the IPMI\ncredentials to their default value, you can issue the following command."}]},{"type":"element","tag":"pre","props":{"code":"# ipmitool raw 0x3c 0x40\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"# ipmitool raw 0x3c 0x40\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Where "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"0x3c"}]},{"type":"text","value":" is the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":""}]},{"type":"text","value":" argument, a.k.a. the network function code that defines the functional routing for\nmessages, and "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"0x40"}]},{"type":"text","value":" is the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":""}]},{"type":"text","value":". According to section 5.1 of the "},{"type":"element","tag":"a","props":{"href":"https://www.intel.com/content/dam/www/public/us/en/documents/product-briefs/ipmi-second-gen-interface-spec-v2-rev1-1.pdf","rel":["nofollow"]},"children":[{"type":"text","value":"IPMI interface\nspecification"}]},{"type":"text","value":",\n"},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"netfn"}]},{"type":"text","value":" codes ranging from 0x30 to 0x3F are reserved for vendor specific functions. I searched around for some\nSupermicro references on these vendor specific network functions without much luck other than various "},{"type":"element","tag":"a","props":{"href":"https://www.supermicro.com/support/faqs/faq.cfm?faq=15448","rel":["nofollow"]},"children":[{"type":"text","value":"support\nresponses"}]},{"type":"text","value":" on how to reset a device. Bummer!"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:reset-ipmi-password-from-host-os.md","_source":"content","_file":"articles/reset-ipmi-password-from-host-os.md","_extension":"md"} \ No newline at end of file diff --git a/api/_content/query/7TfxHWYxZH.1726174725311.json b/api/_content/query/TxpJ5sv0HY.1727638383380.json similarity index 53% rename from api/_content/query/7TfxHWYxZH.1726174725311.json rename to api/_content/query/TxpJ5sv0HY.1727638383380.json index e73ba574..f6d5cc0d 100644 --- a/api/_content/query/7TfxHWYxZH.1726174725311.json +++ b/api/_content/query/TxpJ5sv0HY.1727638383380.json @@ -1 +1 @@ -{"_path":"/articles/fennel-initial-exploration","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Impressions of Fennel with Hammerspoon","description":"A while back I read an introductory book on Lisp programming titled, \"The Little\nSchemer\". This book opened my mind to new (to me) programming paradigms, and left me\nwith a strong desire to find a way to incorporate Lisp programming into my every day\nlife. It took some time, but I believe I've found what I've been looking for: Fennel.","draft":false,"date":"2023-10-22","tags":["lisp","hammerspoon","fennel"],"categories":["lisp"],"cover_image":"/images/dall-e-fennel-hammer.jpeg","excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"A while back I read an introductory book on Lisp programming titled, \"The Little\nSchemer\". This book opened my mind to new (to me) programming paradigms, and left me\nwith a strong desire to find a way to incorporate Lisp programming into my every day\nlife. It took some time, but I believe I've found what I've been looking for: Fennel."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"A while back I read an introductory book on Lisp programming titled, \"The Little\nSchemer\". This book opened my mind to new (to me) programming paradigms, and left me\nwith a strong desire to find a way to incorporate Lisp programming into my every day\nlife. It took some time, but I believe I've found what I've been looking for: Fennel."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The "},{"type":"element","tag":"a","props":{"href":"https://fennel-lang.org/","rel":["nofollow"]},"children":[{"type":"text","value":"Fennel"}]},{"type":"text","value":" programming language is a dialect of Lisp that boasts compatibility with\nLua, and it just so happens that two of my favorite applications are configured with\nexactly that language: "},{"type":"element","tag":"a","props":{"href":"https://www.hammerspoon.org/","rel":["nofollow"]},"children":[{"type":"text","value":"Hammerspoon"}]},{"type":"text","value":", and "},{"type":"element","tag":"a","props":{"href":"https://neovim.io/","rel":["nofollow"]},"children":[{"type":"text","value":"Neovim"}]},{"type":"text","value":"."}]},{"type":"element","tag":"h2","props":{"id":"initial-observations"},"children":[{"type":"text","value":"Initial Observations"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"To initially explore Fennel, I wanted to start small. My Hammerspoon configuration\nconsists of 7 "},{"type":"element","tag":"a","props":{"href":"https://github.com/cmpadden/dotfiles/tree/795749fa17e1310bb001bb7deaa22be8689f0027/hammerspoon/.hammerspoon/modules","rel":["nofollow"]},"children":[{"type":"text","value":"modules"}]},{"type":"text","value":" that I use for operations such as: launching applications,\nmanaging windows, keeping my computer from going to sleep, and general operating system\nautomation. So the plan is to translate these modules into Fennel, while maintaining\nwithout breaking the existing functionality. However, at this point, I wasn't even sure\nhow to embed Fennel into my project..."}]},{"type":"element","tag":"h2","props":{"id":"integrating-fennel-with-hammerspoon"},"children":[{"type":"text","value":"Integrating Fennel with Hammerspoon"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"While official documentation exists describing how to "},{"type":"element","tag":"a","props":{"href":"https://fennel-lang.org/setup#embedding-fennel","rel":["nofollow"]},"children":[{"type":"text","value":"embed fennel"}]},{"type":"text","value":" into your\nproject; it didn't provide me with enough clarity to know my next steps on integrating\nit with Hammerspoon. I found a few resources online demonstrating how to extend the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"package.path"}]},{"type":"text","value":" and "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"package.cpath"}]},{"type":"text","value":" properties in Lua, but I was unable to get this to\nwork."}]},{"type":"element","tag":"ul","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://blog.exupero.org/hammerspoon-with-fennel/","rel":["nofollow"]},"children":[{"type":"text","value":"https://blog.exupero.org/hammerspoon-with-fennel/"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/Hammerspoon/hammerspoon/issues/2377#issuecomment-636331435","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/Hammerspoon/hammerspoon/issues/2377#issuecomment-636331435"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/agzam/spacehammer/blob/master/init.lua","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/agzam/spacehammer/blob/master/init.lua"}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Ultimately, I opted to include the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"fennel.lua"}]},{"type":"text","value":" file to my Hammerspoon configuration,\nand while not ideal, it does make the configuration nicely self-contained. I'll leave it\nas a future task to include the module installed with LuaRocks."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"With Fennel now included in my Hammerspoon configuration, all I need to do is configure\nthe "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"fennel.path"}]},{"type":"text","value":" to point to the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"*.fnl"}]},{"type":"text","value":" files in the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":".hammerspoon/"}]},{"type":"text","value":" directory, and\nttranslating these modules can begin!"}]},{"type":"element","tag":"pre","props":{"className":"language-lua shiki shiki-themes github-light","code":"-- init.lua\n\nlocal fennel = require('fennel')\n\nfennel.path = package.path .. \";\" .. os.getenv(\"HOME\") .. \"/.hammerspoon/?.fnl\"\n\ntable.insert(package.loaders or package.searchers, fennel.searcher)\n\nrequire 'main'\n","language":"lua","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"-- init.lua\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"local"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" fennel "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" require"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'fennel'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"fennel."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"path"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" package.path"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" .."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \";\" "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":".."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" os.getenv"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"HOME\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":".."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"/.hammerspoon/?.fnl\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"table.insert"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"package.loaders"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" or"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" package.searchers"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", fennel."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"searcher"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"require"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 'main'\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"translating-lua-to-fennel"},"children":[{"type":"text","value":"Translating Lua to Fennel"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"As a Fennel novice, I was happy to see that the Fennel project provides an online\ncross-compiler for Lua and Fennel called "},{"type":"element","tag":"a","props":{"href":"https://fennel-lang.org/see","rel":["nofollow"]},"children":[{"type":"text","value":"anti-fennel"}]},{"type":"text","value":", and while it can generate some\nstrange-looking Fennel code, it was an extremely useful tool for me to get\nup-and-running right away. For example, by pasting the simple "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sleep"}]},{"type":"text","value":" function\nfrom the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"helpers"}]},{"type":"text","value":" module into the compiler:"}]},{"type":"element","tag":"pre","props":{"className":"language-lua shiki shiki-themes github-light","code":"function sleep(ms)\n os.execute(\"sleep \" .. tonumber(ms) / 1000)\nend\n","language":"lua","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"function"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" sleep"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(ms)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" os.execute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"sleep \" "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":".."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" tonumber"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(ms) "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"/"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1000"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"end\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"className":"language-lisp shiki shiki-themes github-light","code":"(fn sleep [ms]\n (os.execute (.. \"sleep \" (/ (tonumber ms) 1000))))\n","language":"lisp","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(fn "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"sleep"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" [ms]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (os.execute (.. "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"sleep \""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"/"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (tonumber ms) "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"1000"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"))))\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"As another example, here is the output for my "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"caffeine"}]},{"type":"text","value":" toggle:"}]},{"type":"element","tag":"pre","props":{"className":"language-lua shiki shiki-themes github-light","code":"hs.hotkey.bind(HYPER, \"0\", function()\n hs.caffeinate.toggle(\"displayIdle\")\n if hs.caffeinate.get(\"displayIdle\") then\n helpers:show(\"Caffeine Enabled\", nil, helpers.styles.success, helpers.assets.check)\n else\n helpers:show(\"Caffeine Disabled\", nil, helpers.styles.error, helpers.assets.ban)\n end\nend)\n","language":"lua","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"hs."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"hotkey"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"bind"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(HYPER, "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"0\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"function"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"()\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" hs."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"caffeinate"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"toggle"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"displayIdle\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" if"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" hs."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"caffeinate"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"get"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"displayIdle\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"then\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" helpers"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":":"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"show"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Caffeine Enabled\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"nil"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", helpers."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"styles"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"success"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", helpers."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"assets"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"check"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" else\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" helpers"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":":"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"show"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Caffeine Disabled\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"nil"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", helpers."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"styles"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"error"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", helpers."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"assets"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"ban"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" end\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"end"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"className":"language-lisp shiki shiki-themes github-light","code":"(hs.hotkey.bind HYPER :0\n (fn [] (hs.caffeinate.toggle :displayIdle)\n (if (hs.caffeinate.get :displayIdle)\n (helpers:show \"Caffeine Enabled\" nil helpers.styles.success helpers.assets.check)\n (helpers:show \"Caffeine Disabled\" nil helpers.styles.error helpers.assets.ban)))) \n","language":"lisp","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(hs.hotkey.bind HYPER "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":":0\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (fn [] (hs.caffeinate.toggle "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":":displayIdle"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"if"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (hs.caffeinate.get "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":":displayIdle"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"helpers"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":":show "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Caffeine Enabled\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" nil"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" helpers.styles.success helpers.assets.check)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"helpers"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":":show "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Caffeine Disabled\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" nil"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" helpers.styles.error helpers.assets.ban))))\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This was especially helpful for more gnarly modules like the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"window"}]},{"type":"text","value":" module used for\nwindow management, and seeing the Lua and Fennel code side-by-side was a kick starter in\nlearning the language!"}]},{"type":"element","tag":"h2","props":{"id":"next-steps"},"children":[{"type":"text","value":"Next Steps"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"While my Fennel Hammerspoon configuration now works with parity to its Lua counterpart,\nI have not yet added new features or modules. I look forward to writing new Fennel code,\nand deepen my understanding of Lisp and the Fennel programming language."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Additionally, before beginning this endeavor, I was already aware of projects like\n"},{"type":"element","tag":"a","props":{"href":"https://github.com/agzam/spacehammer","rel":["nofollow"]},"children":[{"type":"text","value":"spacehammer"}]},{"type":"text","value":"; a wildly impressive Hammerspoon configuration written in Fennel, but,\nI wanted to start small and learn the integration myself. However, with the basics out\nof the way, I hope to explore this project further, and seek lessons-learned for the\nconfiguration of my own."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The full pull-request for translating my Lua Hammerspoon configuration to Fennel can be\nfound here: "},{"type":"element","tag":"a","props":{"href":"https://github.com/cmpadden/dotfiles/pull/19/files","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/cmpadden/dotfiles/pull/19/files"}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"initial-observations","depth":2,"text":"Initial Observations"},{"id":"integrating-fennel-with-hammerspoon","depth":2,"text":"Integrating Fennel with Hammerspoon"},{"id":"translating-lua-to-fennel","depth":2,"text":"Translating Lua to Fennel"},{"id":"next-steps","depth":2,"text":"Next Steps"}]}},"_type":"markdown","_id":"content:articles:fennel-initial-exploration.md","_source":"content","_file":"articles/fennel-initial-exploration.md","_stem":"articles/fennel-initial-exploration","_extension":"md"} \ No newline at end of file +{"_path":"/articles/fennel-initial-exploration","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Impressions of Fennel with Hammerspoon","description":"A while back I read an introductory book on Lisp programming titled, \"The Little\nSchemer\". This book opened my mind to new (to me) programming paradigms, and left me\nwith a strong desire to find a way to incorporate Lisp programming into my every day\nlife. It took some time, but I believe I've found what I've been looking for: Fennel.","draft":false,"date":"2023-10-22","tags":["lisp","hammerspoon","fennel"],"categories":["lisp"],"cover_image":"/images/dall-e-fennel-hammer.jpeg","excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"A while back I read an introductory book on Lisp programming titled, \"The Little\nSchemer\". This book opened my mind to new (to me) programming paradigms, and left me\nwith a strong desire to find a way to incorporate Lisp programming into my every day\nlife. It took some time, but I believe I've found what I've been looking for: Fennel."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"A while back I read an introductory book on Lisp programming titled, \"The Little\nSchemer\". This book opened my mind to new (to me) programming paradigms, and left me\nwith a strong desire to find a way to incorporate Lisp programming into my every day\nlife. It took some time, but I believe I've found what I've been looking for: Fennel."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The "},{"type":"element","tag":"a","props":{"href":"https://fennel-lang.org/","rel":["nofollow"]},"children":[{"type":"text","value":"Fennel"}]},{"type":"text","value":" programming language is a dialect of Lisp that boasts compatibility with\nLua, and it just so happens that two of my favorite applications are configured with\nexactly that language: "},{"type":"element","tag":"a","props":{"href":"https://www.hammerspoon.org/","rel":["nofollow"]},"children":[{"type":"text","value":"Hammerspoon"}]},{"type":"text","value":", and "},{"type":"element","tag":"a","props":{"href":"https://neovim.io/","rel":["nofollow"]},"children":[{"type":"text","value":"Neovim"}]},{"type":"text","value":"."}]},{"type":"element","tag":"h2","props":{"id":"initial-observations"},"children":[{"type":"text","value":"Initial Observations"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"To initially explore Fennel, I wanted to start small. My Hammerspoon configuration\nconsists of 7 "},{"type":"element","tag":"a","props":{"href":"https://github.com/cmpadden/dotfiles/tree/795749fa17e1310bb001bb7deaa22be8689f0027/hammerspoon/.hammerspoon/modules","rel":["nofollow"]},"children":[{"type":"text","value":"modules"}]},{"type":"text","value":" that I use for operations such as: launching applications,\nmanaging windows, keeping my computer from going to sleep, and general operating system\nautomation. So the plan is to translate these modules into Fennel, while maintaining\nwithout breaking the existing functionality. However, at this point, I wasn't even sure\nhow to embed Fennel into my project..."}]},{"type":"element","tag":"h2","props":{"id":"integrating-fennel-with-hammerspoon"},"children":[{"type":"text","value":"Integrating Fennel with Hammerspoon"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"While official documentation exists describing how to "},{"type":"element","tag":"a","props":{"href":"https://fennel-lang.org/setup#embedding-fennel","rel":["nofollow"]},"children":[{"type":"text","value":"embed fennel"}]},{"type":"text","value":" into your\nproject; it didn't provide me with enough clarity to know my next steps on integrating\nit with Hammerspoon. I found a few resources online demonstrating how to extend the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"package.path"}]},{"type":"text","value":" and "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"package.cpath"}]},{"type":"text","value":" properties in Lua, but I was unable to get this to\nwork."}]},{"type":"element","tag":"ul","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://blog.exupero.org/hammerspoon-with-fennel/","rel":["nofollow"]},"children":[{"type":"text","value":"https://blog.exupero.org/hammerspoon-with-fennel/"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/Hammerspoon/hammerspoon/issues/2377#issuecomment-636331435","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/Hammerspoon/hammerspoon/issues/2377#issuecomment-636331435"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://github.com/agzam/spacehammer/blob/master/init.lua","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/agzam/spacehammer/blob/master/init.lua"}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Ultimately, I opted to include the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"fennel.lua"}]},{"type":"text","value":" file to my Hammerspoon configuration,\nand while not ideal, it does make the configuration nicely self-contained. I'll leave it\nas a future task to include the module installed with LuaRocks."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"With Fennel now included in my Hammerspoon configuration, all I need to do is configure\nthe "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"fennel.path"}]},{"type":"text","value":" to point to the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"*.fnl"}]},{"type":"text","value":" files in the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":".hammerspoon/"}]},{"type":"text","value":" directory, and\nttranslating these modules can begin!"}]},{"type":"element","tag":"pre","props":{"className":"language-lua shiki shiki-themes github-light","code":"-- init.lua\n\nlocal fennel = require('fennel')\n\nfennel.path = package.path .. \";\" .. os.getenv(\"HOME\") .. \"/.hammerspoon/?.fnl\"\n\ntable.insert(package.loaders or package.searchers, fennel.searcher)\n\nrequire 'main'\n","language":"lua","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"-- init.lua\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"local"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" fennel "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" require"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'fennel'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"fennel."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"path"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" package.path"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" .."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \";\" "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":".."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" os.getenv"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"HOME\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":".."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"/.hammerspoon/?.fnl\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"table.insert"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"package.loaders"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" or"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" package.searchers"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", fennel."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"searcher"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"require"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 'main'\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"translating-lua-to-fennel"},"children":[{"type":"text","value":"Translating Lua to Fennel"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"As a Fennel novice, I was happy to see that the Fennel project provides an online\ncross-compiler for Lua and Fennel called "},{"type":"element","tag":"a","props":{"href":"https://fennel-lang.org/see","rel":["nofollow"]},"children":[{"type":"text","value":"anti-fennel"}]},{"type":"text","value":", and while it can generate some\nstrange-looking Fennel code, it was an extremely useful tool for me to get\nup-and-running right away. For example, by pasting the simple "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sleep"}]},{"type":"text","value":" function\nfrom the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"helpers"}]},{"type":"text","value":" module into the compiler:"}]},{"type":"element","tag":"pre","props":{"className":"language-lua shiki shiki-themes github-light","code":"function sleep(ms)\n os.execute(\"sleep \" .. tonumber(ms) / 1000)\nend\n","language":"lua","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"function"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" sleep"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(ms)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" os.execute"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"sleep \" "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":".."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" tonumber"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(ms) "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"/"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1000"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"end\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"className":"language-lisp shiki shiki-themes github-light","code":"(fn sleep [ms]\n (os.execute (.. \"sleep \" (/ (tonumber ms) 1000))))\n","language":"lisp","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(fn sleep [ms]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (os.execute (.. "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"sleep \""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"/"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (tonumber ms) "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"1000"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"))))\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"As another example, here is the output for my "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"caffeine"}]},{"type":"text","value":" toggle:"}]},{"type":"element","tag":"pre","props":{"className":"language-lua shiki shiki-themes github-light","code":"hs.hotkey.bind(HYPER, \"0\", function()\n hs.caffeinate.toggle(\"displayIdle\")\n if hs.caffeinate.get(\"displayIdle\") then\n helpers:show(\"Caffeine Enabled\", nil, helpers.styles.success, helpers.assets.check)\n else\n helpers:show(\"Caffeine Disabled\", nil, helpers.styles.error, helpers.assets.ban)\n end\nend)\n","language":"lua","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"hs."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"hotkey"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"bind"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(HYPER, "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"0\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"function"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"()\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" hs."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"caffeinate"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"toggle"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"displayIdle\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" if"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" hs."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"caffeinate"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"get"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"displayIdle\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"then\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" helpers"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":":"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"show"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Caffeine Enabled\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"nil"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", helpers."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"styles"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"success"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", helpers."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"assets"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"check"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" else\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" helpers"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":":"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"show"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Caffeine Disabled\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"nil"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", helpers."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"styles"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"error"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", helpers."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"assets"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"ban"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" end\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"end"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]}]}]},{"type":"element","tag":"pre","props":{"className":"language-lisp shiki shiki-themes github-light","code":"(hs.hotkey.bind HYPER :0\n (fn [] (hs.caffeinate.toggle :displayIdle)\n (if (hs.caffeinate.get :displayIdle)\n (helpers:show \"Caffeine Enabled\" nil helpers.styles.success helpers.assets.check)\n (helpers:show \"Caffeine Disabled\" nil helpers.styles.error helpers.assets.ban)))) \n","language":"lisp","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(hs.hotkey.bind HYPER "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":":0\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (fn [] (hs.caffeinate.toggle "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":":displayIdle"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"if"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (hs.caffeinate.get "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":":displayIdle"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":")\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (helpers:show "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Caffeine Enabled\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" nil"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" helpers.styles.success helpers.assets.check)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (helpers:show "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Caffeine Disabled\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" nil"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" helpers.styles.error helpers.assets.ban))))\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This was especially helpful for more gnarly modules like the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"window"}]},{"type":"text","value":" module used for\nwindow management, and seeing the Lua and Fennel code side-by-side was a kick starter in\nlearning the language!"}]},{"type":"element","tag":"h2","props":{"id":"next-steps"},"children":[{"type":"text","value":"Next Steps"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"While my Fennel Hammerspoon configuration now works with parity to its Lua counterpart,\nI have not yet added new features or modules. I look forward to writing new Fennel code,\nand deepen my understanding of Lisp and the Fennel programming language."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Additionally, before beginning this endeavor, I was already aware of projects like\n"},{"type":"element","tag":"a","props":{"href":"https://github.com/agzam/spacehammer","rel":["nofollow"]},"children":[{"type":"text","value":"spacehammer"}]},{"type":"text","value":"; a wildly impressive Hammerspoon configuration written in Fennel, but,\nI wanted to start small and learn the integration myself. However, with the basics out\nof the way, I hope to explore this project further, and seek lessons-learned for the\nconfiguration of my own."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The full pull-request for translating my Lua Hammerspoon configuration to Fennel can be\nfound here: "},{"type":"element","tag":"a","props":{"href":"https://github.com/cmpadden/dotfiles/pull/19/files","rel":["nofollow"]},"children":[{"type":"text","value":"https://github.com/cmpadden/dotfiles/pull/19/files"}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"initial-observations","depth":2,"text":"Initial Observations"},{"id":"integrating-fennel-with-hammerspoon","depth":2,"text":"Integrating Fennel with Hammerspoon"},{"id":"translating-lua-to-fennel","depth":2,"text":"Translating Lua to Fennel"},{"id":"next-steps","depth":2,"text":"Next Steps"}]}},"_type":"markdown","_id":"content:articles:fennel-initial-exploration.md","_source":"content","_file":"articles/fennel-initial-exploration.md","_extension":"md"} \ No newline at end of file diff --git a/api/_content/query/bXj5vj6Ts0.1726174725311.json b/api/_content/query/bXj5vj6Ts0.1727638383380.json similarity index 100% rename from api/_content/query/bXj5vj6Ts0.1726174725311.json rename to api/_content/query/bXj5vj6Ts0.1727638383380.json diff --git a/api/_content/query/98CVAb0zLR.1726174725311.json b/api/_content/query/cOxeB6k0CX.1727638383380.json similarity index 98% rename from api/_content/query/98CVAb0zLR.1726174725311.json rename to api/_content/query/cOxeB6k0CX.1727638383380.json index 05f77075..5e5eac55 100644 --- a/api/_content/query/98CVAb0zLR.1726174725311.json +++ b/api/_content/query/cOxeB6k0CX.1727638383380.json @@ -1 +1 @@ -{"_path":"/articles/migrate-truenas-from-core-to-scale","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Migrate to TrueNAS Scale from TrueNAS Core","description":"TrueNAS Scale offers a variety of interesting features that are not supported in its TrueNAS Core counterpart. Most notably, because the base operating system is Debian Linux, opposed to FreeBSD, there is native support for Linux containers via Docker, and Kubernetes Pods! This post walks through the steps required to upgrade from TrueNAS Core to TrueNAS Scale.","date":"2021-12-28","tags":["homelab","supermicro","truenas"],"categories":["homelab"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"TrueNAS Scale offers a variety of interesting features that are not supported in its TrueNAS Core counterpart. Most notably, because the base operating system is Debian Linux, opposed to FreeBSD, there is native support for Linux containers via Docker, and Kubernetes Pods! This post walks through the steps required to upgrade from TrueNAS Core to TrueNAS Scale."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"TrueNAS Scale offers a variety of interesting features that are not supported in its TrueNAS Core counterpart. Most notably, because the base operating system is Debian Linux, opposed to FreeBSD, there is native support for Linux containers via Docker, and Kubernetes Pods! This post walks through the steps required to upgrade from TrueNAS Core to TrueNAS Scale."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Thankfully, the upgrade procedure to migrate from TrueNAS Core to TrueNAS Scale is relatively straight forward. All it requires is to create a bootable USB of the TrueNAS Scale image, boot the USB, and select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Install/Upgrade"}]},{"type":"text","value":" in the installation wizard. But for the sake of being thorough, you can find instructions on how to backup system configurations and install the OS below."}]},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Make a backup of your system’s configuration\n"},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Navigate to "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"System > General"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Click "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Save Config"}]},{"type":"text","value":", check the "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Export Secret Seed"}]},{"type":"text","value":" box, and click "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Save"}]}]}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Export dataset keys for the encrypted pools\n"},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Navigate to "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Storage > Pools"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Click the cog icon, and select "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Export Dataset Keys"}]}]}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Insert the TrueNAS Core bootable USB into the NAS"}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"From the Supermicro IPMI interface select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Remote Control"}]},{"type":"text","value":" and "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"iKVM/HTML5"}]},{"type":"text","value":" and select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Reboot"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Select the bootable USB as the boot device"}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"From the TrueNAS installation wizard, select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Install/Upgrade"}]},{"type":"text","value":", select the drive that contains the TrueNAS installation, and select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Upgrade Install"}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Reboot the device, and voila — you should be up-and-running! Give the system a quick rundown to validate that your settings and pools have transferred correctly, and then enjoy all the container goodness!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"For a breakdown of the differences between TrueNAS Core, Enterprise, and Scale, you can reference "},{"type":"element","tag":"a","props":{"href":"https://www.truenas.com/help-me-choose/","rel":["nofollow"]},"children":[{"type":"text","value":"this table"}]},{"type":"text","value":"."}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:migrate-truenas-from-core-to-scale.md","_source":"content","_file":"articles/migrate-truenas-from-core-to-scale.md","_stem":"articles/migrate-truenas-from-core-to-scale","_extension":"md"} \ No newline at end of file +{"_path":"/articles/migrate-truenas-from-core-to-scale","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Migrate to TrueNAS Scale from TrueNAS Core","description":"TrueNAS Scale offers a variety of interesting features that are not supported in its TrueNAS Core counterpart. Most notably, because the base operating system is Debian Linux, opposed to FreeBSD, there is native support for Linux containers via Docker, and Kubernetes Pods! This post walks through the steps required to upgrade from TrueNAS Core to TrueNAS Scale.","date":"2021-12-28","tags":["homelab","supermicro","truenas"],"categories":["homelab"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"TrueNAS Scale offers a variety of interesting features that are not supported in its TrueNAS Core counterpart. Most notably, because the base operating system is Debian Linux, opposed to FreeBSD, there is native support for Linux containers via Docker, and Kubernetes Pods! This post walks through the steps required to upgrade from TrueNAS Core to TrueNAS Scale."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"TrueNAS Scale offers a variety of interesting features that are not supported in its TrueNAS Core counterpart. Most notably, because the base operating system is Debian Linux, opposed to FreeBSD, there is native support for Linux containers via Docker, and Kubernetes Pods! This post walks through the steps required to upgrade from TrueNAS Core to TrueNAS Scale."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Thankfully, the upgrade procedure to migrate from TrueNAS Core to TrueNAS Scale is relatively straight forward. All it requires is to create a bootable USB of the TrueNAS Scale image, boot the USB, and select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Install/Upgrade"}]},{"type":"text","value":" in the installation wizard. But for the sake of being thorough, you can find instructions on how to backup system configurations and install the OS below."}]},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Make a backup of your system’s configuration\n"},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Navigate to "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"System > General"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Click "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Save Config"}]},{"type":"text","value":", check the "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Export Secret Seed"}]},{"type":"text","value":" box, and click "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Save"}]}]}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Export dataset keys for the encrypted pools\n"},{"type":"element","tag":"ol","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Navigate to "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Storage > Pools"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Click the cog icon, and select "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"Export Dataset Keys"}]}]}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Insert the TrueNAS Core bootable USB into the NAS"}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"From the Supermicro IPMI interface select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Remote Control"}]},{"type":"text","value":" and "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"iKVM/HTML5"}]},{"type":"text","value":" and select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Reboot"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"Select the bootable USB as the boot device"}]},{"type":"element","tag":"li","props":{},"children":[{"type":"text","value":"From the TrueNAS installation wizard, select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Install/Upgrade"}]},{"type":"text","value":", select the drive that contains the TrueNAS installation, and select "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Upgrade Install"}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Reboot the device, and voila — you should be up-and-running! Give the system a quick rundown to validate that your settings and pools have transferred correctly, and then enjoy all the container goodness!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"For a breakdown of the differences between TrueNAS Core, Enterprise, and Scale, you can reference "},{"type":"element","tag":"a","props":{"href":"https://www.truenas.com/help-me-choose/","rel":["nofollow"]},"children":[{"type":"text","value":"this table"}]},{"type":"text","value":"."}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:migrate-truenas-from-core-to-scale.md","_source":"content","_file":"articles/migrate-truenas-from-core-to-scale.md","_extension":"md"} \ No newline at end of file diff --git a/api/_content/query/LcWrOc5HNX.1726174725311.json b/api/_content/query/lIKyXFs9L8.1727638383380.json similarity index 99% rename from api/_content/query/LcWrOc5HNX.1726174725311.json rename to api/_content/query/lIKyXFs9L8.1727638383380.json index a8b56dff..aca9d3d2 100644 --- a/api/_content/query/LcWrOc5HNX.1726174725311.json +++ b/api/_content/query/lIKyXFs9L8.1727638383380.json @@ -1 +1 @@ -{"_path":"/articles/quick-tip-rerunning-bash-commands","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Tip: Re-running Bash Commands","description":"Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use sudo for a command that requires\nroot privileges.","date":"2021-09-22","draft":false,"tags":["tip","bash"],"categories":["tips"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sudo"}]},{"type":"text","value":" for a command that requires\nroot privileges."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sudo"}]},{"type":"text","value":" for a command that requires\nroot privileges."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ pacman -Syu\nerror: you cannot perform this operation unless you are root.\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pacman"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -Syu\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"error:"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" you"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" cannot"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" perform"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" this"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" operation"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" unless"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" you"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" are"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" root.\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Well, I have good news for you -- you can easily re-issue a command with the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!!"}]},{"type":"text","value":" designator! Simply type "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sudo"}]},{"type":"text","value":" followed by "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!!"}]},{"type":"text","value":" and you're good to go."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ sudo !!\nsudo pacman -Syu\n[sudo] password for colton:\n:: Synchronizing package databases...\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" !!\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pacman"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -Syu\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[sudo] password "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"for"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" colton:\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"::"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" Synchronizing"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" package"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" databases...\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"--"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Commands that are prefixed with a bang, "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!"}]},{"type":"text","value":", are considered "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Event\nDesignators,"}]},{"type":"text","value":" and are references to your command-line history. You can take a\nlook at your history with the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"history"}]},{"type":"text","value":" command."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ history\n 1021 touch hello_world.txt\n 1022 ls\n 1023 echo \"Here we go again!\"\n 1024 find . -name *.py\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" history\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" 1021"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" touch"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" hello_world.txt\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" 1022"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ls\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" 1023"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" echo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"Here we go again!\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" 1024"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" find"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -name"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" *"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":".py\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"There are many ways to use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!"}]},{"type":"text","value":" in your shell. For example, if you wanted to\nre-issue a specific command in your history, you could use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!n"}]},{"type":"text","value":" where "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"n"}]},{"type":"text","value":" is\nthe number next to the command in your history."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ !1023\necho \"Here we go again!\"\nHere we go again!\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" !1023\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"echo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"Here we go again!\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"Here"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" we"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" go"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" again!\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Or... if you wanted to run the command you issued 4-commands ago, you can use\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!-4"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ !-4\nls\nhello_world.txt\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" !-4\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"ls\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"hello_world.txt\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Or... if you wanted to run the last command that started with the string\n"},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"find"}]},{"type":"text","value":", you can use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!find"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ !find\nfind . -name *.py\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" !find\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"find"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -name"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" *"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":".py\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Be sure to check out the "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Event Designators"}]},{"type":"text","value":" section of the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"bash"}]},{"type":"text","value":" "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"man"}]},{"type":"text","value":" pages\nfor more information!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"--"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"As an aside, for even faster command-line history navigation, be sure to check\nout the excellent "},{"type":"element","tag":"a","props":{"href":"https://github.com/junegunn/fzf","rel":["nofollow"]},"children":[{"type":"text","value":"fzf"}]},{"type":"text","value":" utility by "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"junegunn."}]},{"type":"text","value":"\nOne of the many features of "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"fzf"}]},{"type":"text","value":" is browsing and re-issuing commands from your\ncommand-line history with a fuzzy-finder!"}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:quick-tip-rerunning-bash-commands.md","_source":"content","_file":"articles/quick-tip-rerunning-bash-commands.md","_stem":"articles/quick-tip-rerunning-bash-commands","_extension":"md"} \ No newline at end of file +{"_path":"/articles/quick-tip-rerunning-bash-commands","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Tip: Re-running Bash Commands","description":"Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use sudo for a command that requires\nroot privileges.","date":"2021-09-22","draft":false,"tags":["tip","bash"],"categories":["tips"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sudo"}]},{"type":"text","value":" for a command that requires\nroot privileges."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sudo"}]},{"type":"text","value":" for a command that requires\nroot privileges."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ pacman -Syu\nerror: you cannot perform this operation unless you are root.\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pacman"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -Syu\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"error:"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" you"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" cannot"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" perform"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" this"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" operation"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" unless"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" you"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" are"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" root.\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Well, I have good news for you -- you can easily re-issue a command with the\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!!"}]},{"type":"text","value":" designator! Simply type "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sudo"}]},{"type":"text","value":" followed by "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!!"}]},{"type":"text","value":" and you're good to go."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ sudo !!\nsudo pacman -Syu\n[sudo] password for colton:\n:: Synchronizing package databases...\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" !!\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"sudo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" pacman"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -Syu\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[sudo] password "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"for"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" colton:\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"::"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" Synchronizing"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" package"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" databases...\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"--"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Commands that are prefixed with a bang, "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!"}]},{"type":"text","value":", are considered "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Event\nDesignators,"}]},{"type":"text","value":" and are references to your command-line history. You can take a\nlook at your history with the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"history"}]},{"type":"text","value":" command."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ history\n 1021 touch hello_world.txt\n 1022 ls\n 1023 echo \"Here we go again!\"\n 1024 find . -name *.py\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" history\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" 1021"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" touch"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" hello_world.txt\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" 1022"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ls\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" 1023"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" echo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"Here we go again!\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" 1024"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" find"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -name"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" *"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":".py\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"There are many ways to use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!"}]},{"type":"text","value":" in your shell. For example, if you wanted to\nre-issue a specific command in your history, you could use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!n"}]},{"type":"text","value":" where "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"n"}]},{"type":"text","value":" is\nthe number next to the command in your history."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ !1023\necho \"Here we go again!\"\nHere we go again!\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" !1023\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"echo"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"Here we go again!\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"Here"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" we"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" go"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" again!\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Or... if you wanted to run the command you issued 4-commands ago, you can use\n"},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!-4"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ !-4\nls\nhello_world.txt\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" !-4\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"ls\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"hello_world.txt\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Or... if you wanted to run the last command that started with the string\n"},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"find"}]},{"type":"text","value":", you can use "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"!find"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"className":"language-bash shiki shiki-themes github-light","code":"$ !find\nfind . -name *.py\n","language":"bash","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" !find\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"find"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -name"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" *"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":".py\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Be sure to check out the "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"Event Designators"}]},{"type":"text","value":" section of the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"bash"}]},{"type":"text","value":" "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"man"}]},{"type":"text","value":" pages\nfor more information!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"--"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"As an aside, for even faster command-line history navigation, be sure to check\nout the excellent "},{"type":"element","tag":"a","props":{"href":"https://github.com/junegunn/fzf","rel":["nofollow"]},"children":[{"type":"text","value":"fzf"}]},{"type":"text","value":" utility by "},{"type":"element","tag":"em","props":{},"children":[{"type":"text","value":"junegunn."}]},{"type":"text","value":"\nOne of the many features of "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"fzf"}]},{"type":"text","value":" is browsing and re-issuing commands from your\ncommand-line history with a fuzzy-finder!"}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:quick-tip-rerunning-bash-commands.md","_source":"content","_file":"articles/quick-tip-rerunning-bash-commands.md","_extension":"md"} \ No newline at end of file diff --git a/api/_content/query/d7v45RMayO.1726174725311.json b/api/_content/query/ph6vNEpVOi.1727638383380.json similarity index 99% rename from api/_content/query/d7v45RMayO.1726174725311.json rename to api/_content/query/ph6vNEpVOi.1727638383380.json index 4b52da8d..ca4ecbe7 100644 --- a/api/_content/query/d7v45RMayO.1726174725311.json +++ b/api/_content/query/ph6vNEpVOi.1727638383380.json @@ -1 +1 @@ -{"_path":"/articles/podcast-transcription-whispercpp","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Easily Transcribe Podcasts with Whisper.cpp","description":"If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive whisper.cpp project. This high-performance fork of OpenAI's Whisper can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the Alter Everything podcast.","draft":false,"date":"2024-01-08","tags":["whisper.cpp","ml"],"categories":["programming"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive "},{"type":"element","tag":"a","props":{"href":"https://github.com/ggerganov/whisper.cpp","rel":["nofollow"]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" project. This high-performance fork of "},{"type":"element","tag":"a","props":{"href":"https://github.com/openai/whisper","rel":["nofollow"]},"children":[{"type":"text","value":"OpenAI's Whisper"}]},{"type":"text","value":" can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the "},{"type":"element","tag":"a","props":{"href":"https://podcasts.apple.com/us/podcast/alter-everything/id1356137854","rel":["nofollow"]},"children":[{"type":"text","value":"Alter Everything"}]},{"type":"text","value":" podcast."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive "},{"type":"element","tag":"a","props":{"href":"https://github.com/ggerganov/whisper.cpp","rel":["nofollow"]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" project. This high-performance fork of "},{"type":"element","tag":"a","props":{"href":"https://github.com/openai/whisper","rel":["nofollow"]},"children":[{"type":"text","value":"OpenAI's Whisper"}]},{"type":"text","value":" can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the "},{"type":"element","tag":"a","props":{"href":"https://podcasts.apple.com/us/podcast/alter-everything/id1356137854","rel":["nofollow"]},"children":[{"type":"text","value":"Alter Everything"}]},{"type":"text","value":" podcast."}]},{"type":"element","tag":"h2","props":{"id":"obtain-audio-files"},"children":[{"type":"text","value":"Obtain Audio File(s)"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, let's get the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"wav"}]},{"type":"text","value":" file from YouTube using the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"youtube-dl"}]},{"type":"text","value":" utility. It should be noted that "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" expects "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"wav"}]},{"type":"text","value":" filetypes, and this utility defaults to "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"mp3"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"code":" $ youtube-dl \\\n --extract-audio \\\n --audio-format wav \\\n --output podcast.wav \\\n \"https://www.youtube.com/watch?v=CoUN690wSYQ\"\n","language":"sh","meta":"","className":"language-sh shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" youtube-dl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --extract-audio"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --audio-format"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" wav"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --output"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast.wav"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"https://www.youtube.com/watch?v=CoUN690wSYQ\"\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This file has a 44.1 kHz sample rate, and "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" expects 16 kHz, so let's go ahead and convert that."}]},{"type":"element","tag":"pre","props":{"code":" $ file podcast.wav\npodcast.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz\n\n $ ffmpeg -i podcast.wav -ar 16000 podcast-16khz.wav\n\n $ file podcast-16khz.wav\npodcast-16khz.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 16000 Hz\n\n# NOTE: it looks like it's possible to specify this conversion as a post-process as a\n# flag to the `youtube-dl` command -- I will explore this further next time...\n# youtube-dl --extract-audio --audio-quality 0 --audio-format mp3 --postprocessor-args \"-ar 44100\" %dl%\n","language":"sh","meta":"","className":"language-sh shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" file"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast.wav\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"podcast.wav:"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" RIFF"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ffmpeg"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -i"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast.wav"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -ar"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 16000"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast-16khz.wav\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" file"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast-16khz.wav\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"podcast-16khz.wav:"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" RIFF"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 16000 Hz\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# NOTE: it looks like it's possible to specify this conversion as a post-process as a\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# flag to the `youtube-dl` command -- I will explore this further next time...\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# youtube-dl --extract-audio --audio-quality 0 --audio-format mp3 --postprocessor-args \"-ar 44100\" %dl%\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"build-whispercpp-transcribe-audio"},"children":[{"type":"text","value":"Build "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" & Transcribe Audio"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, let's get the latest version of "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":", download the English Whisper model, and build the example."}]},{"type":"element","tag":"pre","props":{"code":"# Clone the `whisper.cpp` repository\n $ git clone --depth 1 git@github.com:ggerganov/whisper.cpp && cd whisper.cpp\n\n# Download the English Whisper model in `ggml` format\n $ bash ./models/download-ggml-model.sh base.en\n\n# Build the main example\n $ make\n","language":"sh","meta":"","className":"language-sh shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# Clone the `whisper.cpp` repository\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" git"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" clone"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --depth"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" git@github.com:ggerganov/whisper.cpp"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" && "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"cd"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" whisper.cpp\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# Download the English Whisper model in `ggml` format\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" bash"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ./models/download-ggml-model.sh"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" base.en\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# Build the main example\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" make\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And finally, let's transcribe that podcast!"}]},{"type":"element","tag":"pre","props":{"code":" $ ./main \\\n -m ~/workspace/whisper.cpp/models/ggml-base.en.bin \\\n -f ~/Downloads/podcast-16khz.wav \\\n --output-vtt \\\n --output-file out\n\n# whisper_print_timings: load time = 114.71 ms\n# whisper_print_timings: fallbacks = 0 p / 0 h\n# whisper_print_timings: mel time = 692.20 ms\n# whisper_print_timings: sample time = 22278.10 ms / 27893 runs ( 0.80 ms per run)\n# whisper_print_timings: encode time = 10000.75 ms / 55 runs ( 181.83 ms per run)\n# whisper_print_timings: decode time = 331.77 ms / 54 runs ( 6.14 ms per run)\n# whisper_print_timings: batchd time = 45236.73 ms / 27566 runs ( 1.64 ms per run)\n# whisper_print_timings: prompt time = 1921.90 ms / 11832 runs ( 0.16 ms per run)\n# whisper_print_timings: total time = 80709.54 ms\n","language":"sh","meta":"","className":"language-sh shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ./main"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -m"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ~/workspace/whisper.cpp/models/ggml-base.en.bin"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -f"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ~/Downloads/podcast-16khz.wav"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --output-vtt"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --output-file"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" out\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: load time = 114.71 ms\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: fallbacks = 0 p / 0 h\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: mel time = 692.20 ms\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: sample time = 22278.10 ms / 27893 runs ( 0.80 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: encode time = 10000.75 ms / 55 runs ( 181.83 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":12},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: decode time = 331.77 ms / 54 runs ( 6.14 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":13},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: batchd time = 45236.73 ms / 27566 runs ( 1.64 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":14},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: prompt time = 1921.90 ms / 11832 runs ( 0.16 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":15},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: total time = 80709.54 ms\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"A full podcast transcribed in ~80 seconds on an M1 Mac Mini -- not too bad!"}]},{"type":"element","tag":"pre","props":{"code":"# out.vtt\n\n00:00:00.000 --> 00:00:06.480\n >> Hi everyone. We recently launched a short engagement feedback survey for the Alter Everything\n\n00:00:06.480 --> 00:00:11.360\n podcast. Click the link in the episode description wherever you're listening to let us know what\n\n00:00:11.360 --> 00:00:16.320\n you think and help us improve our show.\n\n00:00:16.320 --> 00:00:21.200\n Welcome to Alter Everything, a podcast about data science and analytics culture. I'm Megan\n\n00:00:21.200 --> 00:00:26.440\n Dibble and today I'm talking with Nick Schrock, CTO and founder of Dagster Labs. We discussed\n\n00:00:26.440 --> 00:00:31.560\n data engineering trends, challenges in the field, why he started his company, and what\n\n00:00:31.560 --> 00:00:38.960\n makes him excited about the future of data engineering. Let's get started.\n\n00:00:38.960 --> 00:00:42.720\n >> Hi, Nick. It's great to have you on our show today. Thanks for being here.\n\n00:00:42.720 --> 00:00:43.920\n >> Thanks for having me.\n\n00:00:43.920 --> 00:00:48.280\n >> Yeah. Could you start off by giving an introduction to yourself for our listeners?\n\n00:00:48.280 --> 00:00:52.920\n >> Sure. My name is Nick Schrock. I'm the CTO and founder of Dagster Labs. There's the\n\n00:00:52.920 --> 00:00:59.520\n company behind Dagster, which is a data orchestration framework. Prior to doing this, I was an engineer\n\n00:00:59.520 --> 00:01:05.960\n at Facebook from 2009, 2017. While I was there, I found a team called product infrastructure\n\n00:01:05.960 --> 00:01:09.800\n whose goal was to make our application developers more efficient and productive, and a bunch\n\n00:01:09.800 --> 00:01:13.840\n of open source work came out of that actually, one of which was React, which I had nothing\n\n00:01:13.840 --> 00:01:18.040\n to do with, but actually the CEO of Dagster Labs co-created and I personally co-created\n\n00:01:18.040 --> 00:01:22.640\n GraphQL. So as I like to say, Pete and I were present at the creation of the full hipster\n\n00:01:22.640 --> 00:01:28.680\n stack. I moved on to Facebook in 2017, figuring out what to do next, and this data engineering\n\n00:01:28.680 --> 00:01:32.960\n and data orchestration problem really got me hooked actually quite soon after I left,\n\n00:01:32.960 --> 00:01:36.280\n and the rest is history. I'm sure we'll get into that more.\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"# out.vtt\n\n00:00:00.000 --> 00:00:06.480\n >> Hi everyone. We recently launched a short engagement feedback survey for the Alter Everything\n\n00:00:06.480 --> 00:00:11.360\n podcast. Click the link in the episode description wherever you're listening to let us know what\n\n00:00:11.360 --> 00:00:16.320\n you think and help us improve our show.\n\n00:00:16.320 --> 00:00:21.200\n Welcome to Alter Everything, a podcast about data science and analytics culture. I'm Megan\n\n00:00:21.200 --> 00:00:26.440\n Dibble and today I'm talking with Nick Schrock, CTO and founder of Dagster Labs. We discussed\n\n00:00:26.440 --> 00:00:31.560\n data engineering trends, challenges in the field, why he started his company, and what\n\n00:00:31.560 --> 00:00:38.960\n makes him excited about the future of data engineering. Let's get started.\n\n00:00:38.960 --> 00:00:42.720\n >> Hi, Nick. It's great to have you on our show today. Thanks for being here.\n\n00:00:42.720 --> 00:00:43.920\n >> Thanks for having me.\n\n00:00:43.920 --> 00:00:48.280\n >> Yeah. Could you start off by giving an introduction to yourself for our listeners?\n\n00:00:48.280 --> 00:00:52.920\n >> Sure. My name is Nick Schrock. I'm the CTO and founder of Dagster Labs. There's the\n\n00:00:52.920 --> 00:00:59.520\n company behind Dagster, which is a data orchestration framework. Prior to doing this, I was an engineer\n\n00:00:59.520 --> 00:01:05.960\n at Facebook from 2009, 2017. While I was there, I found a team called product infrastructure\n\n00:01:05.960 --> 00:01:09.800\n whose goal was to make our application developers more efficient and productive, and a bunch\n\n00:01:09.800 --> 00:01:13.840\n of open source work came out of that actually, one of which was React, which I had nothing\n\n00:01:13.840 --> 00:01:18.040\n to do with, but actually the CEO of Dagster Labs co-created and I personally co-created\n\n00:01:18.040 --> 00:01:22.640\n GraphQL. So as I like to say, Pete and I were present at the creation of the full hipster\n\n00:01:22.640 --> 00:01:28.680\n stack. I moved on to Facebook in 2017, figuring out what to do next, and this data engineering\n\n00:01:28.680 --> 00:01:32.960\n and data orchestration problem really got me hooked actually quite soon after I left,\n\n00:01:32.960 --> 00:01:36.280\n and the rest is history. I'm sure we'll get into that more.\n"}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"obtain-audio-files","depth":2,"text":"Obtain Audio File(s)"},{"id":"build-whispercpp-transcribe-audio","depth":2,"text":"Build whisper.cpp & Transcribe Audio"}]}},"_type":"markdown","_id":"content:articles:podcast-transcription-whispercpp.md","_source":"content","_file":"articles/podcast-transcription-whispercpp.md","_stem":"articles/podcast-transcription-whispercpp","_extension":"md"} \ No newline at end of file +{"_path":"/articles/podcast-transcription-whispercpp","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Easily Transcribe Podcasts with Whisper.cpp","description":"If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive whisper.cpp project. This high-performance fork of OpenAI's Whisper can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the Alter Everything podcast.","draft":false,"date":"2024-01-08","tags":["whisper.cpp","ml"],"categories":["programming"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive "},{"type":"element","tag":"a","props":{"href":"https://github.com/ggerganov/whisper.cpp","rel":["nofollow"]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" project. This high-performance fork of "},{"type":"element","tag":"a","props":{"href":"https://github.com/openai/whisper","rel":["nofollow"]},"children":[{"type":"text","value":"OpenAI's Whisper"}]},{"type":"text","value":" can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the "},{"type":"element","tag":"a","props":{"href":"https://podcasts.apple.com/us/podcast/alter-everything/id1356137854","rel":["nofollow"]},"children":[{"type":"text","value":"Alter Everything"}]},{"type":"text","value":" podcast."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive "},{"type":"element","tag":"a","props":{"href":"https://github.com/ggerganov/whisper.cpp","rel":["nofollow"]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" project. This high-performance fork of "},{"type":"element","tag":"a","props":{"href":"https://github.com/openai/whisper","rel":["nofollow"]},"children":[{"type":"text","value":"OpenAI's Whisper"}]},{"type":"text","value":" can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the "},{"type":"element","tag":"a","props":{"href":"https://podcasts.apple.com/us/podcast/alter-everything/id1356137854","rel":["nofollow"]},"children":[{"type":"text","value":"Alter Everything"}]},{"type":"text","value":" podcast."}]},{"type":"element","tag":"h2","props":{"id":"obtain-audio-files"},"children":[{"type":"text","value":"Obtain Audio File(s)"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, let's get the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"wav"}]},{"type":"text","value":" file from YouTube using the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"youtube-dl"}]},{"type":"text","value":" utility. It should be noted that "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" expects "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"wav"}]},{"type":"text","value":" filetypes, and this utility defaults to "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"mp3"}]},{"type":"text","value":"."}]},{"type":"element","tag":"pre","props":{"code":" $ youtube-dl \\\n --extract-audio \\\n --audio-format wav \\\n --output podcast.wav \\\n \"https://www.youtube.com/watch?v=CoUN690wSYQ\"\n","language":"sh","meta":"","className":"language-sh shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" youtube-dl"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --extract-audio"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --audio-format"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" wav"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --output"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast.wav"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"https://www.youtube.com/watch?v=CoUN690wSYQ\"\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This file has a 44.1 kHz sample rate, and "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" expects 16 kHz, so let's go ahead and convert that."}]},{"type":"element","tag":"pre","props":{"code":" $ file podcast.wav\npodcast.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz\n\n $ ffmpeg -i podcast.wav -ar 16000 podcast-16khz.wav\n\n $ file podcast-16khz.wav\npodcast-16khz.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 16000 Hz\n\n# NOTE: it looks like it's possible to specify this conversion as a post-process as a\n# flag to the `youtube-dl` command -- I will explore this further next time...\n# youtube-dl --extract-audio --audio-quality 0 --audio-format mp3 --postprocessor-args \"-ar 44100\" %dl%\n","language":"sh","meta":"","className":"language-sh shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" file"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast.wav\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"podcast.wav:"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" RIFF"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ffmpeg"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -i"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast.wav"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -ar"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 16000"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast-16khz.wav\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" file"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" podcast-16khz.wav\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"podcast-16khz.wav:"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" RIFF"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 16000 Hz\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# NOTE: it looks like it's possible to specify this conversion as a post-process as a\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# flag to the `youtube-dl` command -- I will explore this further next time...\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# youtube-dl --extract-audio --audio-quality 0 --audio-format mp3 --postprocessor-args \"-ar 44100\" %dl%\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"build-whispercpp-transcribe-audio"},"children":[{"type":"text","value":"Build "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":" & Transcribe Audio"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, let's get the latest version of "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"whisper.cpp"}]},{"type":"text","value":", download the English Whisper model, and build the example."}]},{"type":"element","tag":"pre","props":{"code":"# Clone the `whisper.cpp` repository\n $ git clone --depth 1 git@github.com:ggerganov/whisper.cpp && cd whisper.cpp\n\n# Download the English Whisper model in `ggml` format\n $ bash ./models/download-ggml-model.sh base.en\n\n# Build the main example\n $ make\n","language":"sh","meta":"","className":"language-sh shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# Clone the `whisper.cpp` repository\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" git"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" clone"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --depth"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" 1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" git@github.com:ggerganov/whisper.cpp"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" && "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"cd"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" whisper.cpp\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# Download the English Whisper model in `ggml` format\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" bash"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ./models/download-ggml-model.sh"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" base.en\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# Build the main example\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" make\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And finally, let's transcribe that podcast!"}]},{"type":"element","tag":"pre","props":{"code":" $ ./main \\\n -m ~/workspace/whisper.cpp/models/ggml-base.en.bin \\\n -f ~/Downloads/podcast-16khz.wav \\\n --output-vtt \\\n --output-file out\n\n# whisper_print_timings: load time = 114.71 ms\n# whisper_print_timings: fallbacks = 0 p / 0 h\n# whisper_print_timings: mel time = 692.20 ms\n# whisper_print_timings: sample time = 22278.10 ms / 27893 runs ( 0.80 ms per run)\n# whisper_print_timings: encode time = 10000.75 ms / 55 runs ( 181.83 ms per run)\n# whisper_print_timings: decode time = 331.77 ms / 54 runs ( 6.14 ms per run)\n# whisper_print_timings: batchd time = 45236.73 ms / 27566 runs ( 1.64 ms per run)\n# whisper_print_timings: prompt time = 1921.90 ms / 11832 runs ( 0.16 ms per run)\n# whisper_print_timings: total time = 80709.54 ms\n","language":"sh","meta":"","className":"language-sh shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" $"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ./main"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -m"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ~/workspace/whisper.cpp/models/ggml-base.en.bin"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -f"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" ~/Downloads/podcast-16khz.wav"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --output-vtt"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" \\\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --output-file"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" out\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: load time = 114.71 ms\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: fallbacks = 0 p / 0 h\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: mel time = 692.20 ms\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: sample time = 22278.10 ms / 27893 runs ( 0.80 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: encode time = 10000.75 ms / 55 runs ( 181.83 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":12},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: decode time = 331.77 ms / 54 runs ( 6.14 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":13},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: batchd time = 45236.73 ms / 27566 runs ( 1.64 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":14},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: prompt time = 1921.90 ms / 11832 runs ( 0.16 ms per run)\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":15},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":"# whisper_print_timings: total time = 80709.54 ms\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"A full podcast transcribed in ~80 seconds on an M1 Mac Mini -- not too bad!"}]},{"type":"element","tag":"pre","props":{"code":"# out.vtt\n\n00:00:00.000 --> 00:00:06.480\n >> Hi everyone. We recently launched a short engagement feedback survey for the Alter Everything\n\n00:00:06.480 --> 00:00:11.360\n podcast. Click the link in the episode description wherever you're listening to let us know what\n\n00:00:11.360 --> 00:00:16.320\n you think and help us improve our show.\n\n00:00:16.320 --> 00:00:21.200\n Welcome to Alter Everything, a podcast about data science and analytics culture. I'm Megan\n\n00:00:21.200 --> 00:00:26.440\n Dibble and today I'm talking with Nick Schrock, CTO and founder of Dagster Labs. We discussed\n\n00:00:26.440 --> 00:00:31.560\n data engineering trends, challenges in the field, why he started his company, and what\n\n00:00:31.560 --> 00:00:38.960\n makes him excited about the future of data engineering. Let's get started.\n\n00:00:38.960 --> 00:00:42.720\n >> Hi, Nick. It's great to have you on our show today. Thanks for being here.\n\n00:00:42.720 --> 00:00:43.920\n >> Thanks for having me.\n\n00:00:43.920 --> 00:00:48.280\n >> Yeah. Could you start off by giving an introduction to yourself for our listeners?\n\n00:00:48.280 --> 00:00:52.920\n >> Sure. My name is Nick Schrock. I'm the CTO and founder of Dagster Labs. There's the\n\n00:00:52.920 --> 00:00:59.520\n company behind Dagster, which is a data orchestration framework. Prior to doing this, I was an engineer\n\n00:00:59.520 --> 00:01:05.960\n at Facebook from 2009, 2017. While I was there, I found a team called product infrastructure\n\n00:01:05.960 --> 00:01:09.800\n whose goal was to make our application developers more efficient and productive, and a bunch\n\n00:01:09.800 --> 00:01:13.840\n of open source work came out of that actually, one of which was React, which I had nothing\n\n00:01:13.840 --> 00:01:18.040\n to do with, but actually the CEO of Dagster Labs co-created and I personally co-created\n\n00:01:18.040 --> 00:01:22.640\n GraphQL. So as I like to say, Pete and I were present at the creation of the full hipster\n\n00:01:22.640 --> 00:01:28.680\n stack. I moved on to Facebook in 2017, figuring out what to do next, and this data engineering\n\n00:01:28.680 --> 00:01:32.960\n and data orchestration problem really got me hooked actually quite soon after I left,\n\n00:01:32.960 --> 00:01:36.280\n and the rest is history. I'm sure we'll get into that more.\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"# out.vtt\n\n00:00:00.000 --> 00:00:06.480\n >> Hi everyone. We recently launched a short engagement feedback survey for the Alter Everything\n\n00:00:06.480 --> 00:00:11.360\n podcast. Click the link in the episode description wherever you're listening to let us know what\n\n00:00:11.360 --> 00:00:16.320\n you think and help us improve our show.\n\n00:00:16.320 --> 00:00:21.200\n Welcome to Alter Everything, a podcast about data science and analytics culture. I'm Megan\n\n00:00:21.200 --> 00:00:26.440\n Dibble and today I'm talking with Nick Schrock, CTO and founder of Dagster Labs. We discussed\n\n00:00:26.440 --> 00:00:31.560\n data engineering trends, challenges in the field, why he started his company, and what\n\n00:00:31.560 --> 00:00:38.960\n makes him excited about the future of data engineering. Let's get started.\n\n00:00:38.960 --> 00:00:42.720\n >> Hi, Nick. It's great to have you on our show today. Thanks for being here.\n\n00:00:42.720 --> 00:00:43.920\n >> Thanks for having me.\n\n00:00:43.920 --> 00:00:48.280\n >> Yeah. Could you start off by giving an introduction to yourself for our listeners?\n\n00:00:48.280 --> 00:00:52.920\n >> Sure. My name is Nick Schrock. I'm the CTO and founder of Dagster Labs. There's the\n\n00:00:52.920 --> 00:00:59.520\n company behind Dagster, which is a data orchestration framework. Prior to doing this, I was an engineer\n\n00:00:59.520 --> 00:01:05.960\n at Facebook from 2009, 2017. While I was there, I found a team called product infrastructure\n\n00:01:05.960 --> 00:01:09.800\n whose goal was to make our application developers more efficient and productive, and a bunch\n\n00:01:09.800 --> 00:01:13.840\n of open source work came out of that actually, one of which was React, which I had nothing\n\n00:01:13.840 --> 00:01:18.040\n to do with, but actually the CEO of Dagster Labs co-created and I personally co-created\n\n00:01:18.040 --> 00:01:22.640\n GraphQL. So as I like to say, Pete and I were present at the creation of the full hipster\n\n00:01:22.640 --> 00:01:28.680\n stack. I moved on to Facebook in 2017, figuring out what to do next, and this data engineering\n\n00:01:28.680 --> 00:01:32.960\n and data orchestration problem really got me hooked actually quite soon after I left,\n\n00:01:32.960 --> 00:01:36.280\n and the rest is history. I'm sure we'll get into that more.\n"}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"obtain-audio-files","depth":2,"text":"Obtain Audio File(s)"},{"id":"build-whispercpp-transcribe-audio","depth":2,"text":"Build whisper.cpp & Transcribe Audio"}]}},"_type":"markdown","_id":"content:articles:podcast-transcription-whispercpp.md","_source":"content","_file":"articles/podcast-transcription-whispercpp.md","_extension":"md"} \ No newline at end of file diff --git a/api/_content/query/ucEXmLbw2Z.1726174725311.json b/api/_content/query/wVY7dvWXwt.1727638383380.json similarity index 98% rename from api/_content/query/ucEXmLbw2Z.1726174725311.json rename to api/_content/query/wVY7dvWXwt.1727638383380.json index b76fd19c..f8e98189 100644 --- a/api/_content/query/ucEXmLbw2Z.1726174725311.json +++ b/api/_content/query/wVY7dvWXwt.1727638383380.json @@ -1 +1 @@ -{"_path":"/articles/docker-selinux-volumes","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Docker Volume Permissions with SELinux","description":"Unfamiliar with running Docker on a SELinux enabled system, I found myself\nrunning into a bunch of file permission errors while creating volumes.","date":"2019-12-26","draft":false,"tags":["docker","selinux"],"categories":["linux"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Unfamiliar with running Docker on a SELinux enabled system, I found myself\nrunning into a bunch of file permission errors while creating volumes."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Unfamiliar with running Docker on a SELinux enabled system, I found myself\nrunning into a bunch of file permission errors while creating volumes."}]},{"type":"element","tag":"pre","props":{"code":"mkdir: can't create directory '/data': Permission denied\n","language":"txt","meta":"","className":"language-txt shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"mkdir: can't create directory '/data': Permission denied\n"}]}]}]}]},{"type":"element","tag":"hr","props":{},"children":[]},{"type":"element","tag":"pre","props":{"code":"$ docker info --format '{{json .SecurityOptions}}'\n[\n \"name=seccomp,profile=/etc/docker/seccomp.json\",\n \"name=selinux\"\n]\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" docker"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" info"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --format"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" '{{json .SecurityOptions}}'\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"name=seccomp,profile=/etc/docker/seccomp.json\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"name=selinux\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"It turns out that this can be resolved by appending the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":":z"}]},{"type":"text","value":" flag to the volume\nmappings in the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"docker-compose.yml"}]},{"type":"text","value":" file, indicating that the volume content\nis shared."}]},{"type":"element","tag":"pre","props":{"code":"services:\n server:\n volumes:\n - ./data:/data:z\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"services:\n server:\n volumes:\n - ./data:/data:z\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"From the Docker documentation:"}]},{"type":"element","tag":"blockquote","props":{},"children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"z"}]},{"type":"text","value":" option tells Docker that two containers share the volume content. As\na result, Docker labels the content with a shared content label. Shared\nvolume labels allow all containers to read/write content."}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"strong","props":{},"children":[{"type":"text","value":"References"}]}]},{"type":"element","tag":"ul","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.docker.com/engine/reference/commandline/info/","rel":["nofollow"]},"children":[{"type":"text","value":"Docker Docs: Docker Info"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.docker.com/engine/reference/commandline/run/#mount-volumes-from-container---volumes-from","rel":["nofollow"]},"children":[{"type":"text","value":"Docker Docs: Mounting Volumes"}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:docker-selinux-volumes.md","_source":"content","_file":"articles/docker-selinux-volumes.md","_stem":"articles/docker-selinux-volumes","_extension":"md"} \ No newline at end of file +{"_path":"/articles/docker-selinux-volumes","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"Docker Volume Permissions with SELinux","description":"Unfamiliar with running Docker on a SELinux enabled system, I found myself\nrunning into a bunch of file permission errors while creating volumes.","date":"2019-12-26","draft":false,"tags":["docker","selinux"],"categories":["linux"],"excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Unfamiliar with running Docker on a SELinux enabled system, I found myself\nrunning into a bunch of file permission errors while creating volumes."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Unfamiliar with running Docker on a SELinux enabled system, I found myself\nrunning into a bunch of file permission errors while creating volumes."}]},{"type":"element","tag":"pre","props":{"code":"mkdir: can't create directory '/data': Permission denied\n","language":"txt","meta":"","className":"language-txt shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{},"children":[{"type":"text","value":"mkdir: can't create directory '/data': Permission denied\n"}]}]}]}]},{"type":"element","tag":"hr","props":{},"children":[]},{"type":"element","tag":"pre","props":{"code":"$ docker info --format '{{json .SecurityOptions}}'\n[\n \"name=seccomp,profile=/etc/docker/seccomp.json\",\n \"name=selinux\"\n]\n","language":"bash","meta":"","className":"language-bash shiki shiki-themes github-light","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"$"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" docker"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" info"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" --format"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" '{{json .SecurityOptions}}'\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"[\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"name=seccomp,profile=/etc/docker/seccomp.json\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"name=selinux\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"It turns out that this can be resolved by appending the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":":z"}]},{"type":"text","value":" flag to the volume\nmappings in the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"docker-compose.yml"}]},{"type":"text","value":" file, indicating that the volume content\nis shared."}]},{"type":"element","tag":"pre","props":{"code":"services:\n server:\n volumes:\n - ./data:/data:z\n"},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"services:\n server:\n volumes:\n - ./data:/data:z\n"}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"From the Docker documentation:"}]},{"type":"element","tag":"blockquote","props":{},"children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"z"}]},{"type":"text","value":" option tells Docker that two containers share the volume content. As\na result, Docker labels the content with a shared content label. Shared\nvolume labels allow all containers to read/write content."}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"element","tag":"strong","props":{},"children":[{"type":"text","value":"References"}]}]},{"type":"element","tag":"ul","props":{},"children":[{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.docker.com/engine/reference/commandline/info/","rel":["nofollow"]},"children":[{"type":"text","value":"Docker Docs: Docker Info"}]}]},{"type":"element","tag":"li","props":{},"children":[{"type":"element","tag":"a","props":{"href":"https://docs.docker.com/engine/reference/commandline/run/#mount-volumes-from-container---volumes-from","rel":["nofollow"]},"children":[{"type":"text","value":"Docker Docs: Mounting Volumes"}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}},"_type":"markdown","_id":"content:articles:docker-selinux-volumes.md","_source":"content","_file":"articles/docker-selinux-volumes.md","_extension":"md"} \ No newline at end of file diff --git a/api/_content/query/v3HQ7aAWkW.1726174725311.json b/api/_content/query/x8mzqct7Ta.1727638383380.json similarity index 99% rename from api/_content/query/v3HQ7aAWkW.1726174725311.json rename to api/_content/query/x8mzqct7Ta.1727638383380.json index ea26152b..a4c5f2e5 100644 --- a/api/_content/query/v3HQ7aAWkW.1726174725311.json +++ b/api/_content/query/x8mzqct7Ta.1727638383380.json @@ -1 +1 @@ -{"_path":"/articles/nuxt-content-rss-feed","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"How To Add an RSS Feed to a Nuxt Website","description":"If you are a user of Nuxt Content and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application.","draft":false,"date":"2024-01-06","tags":["nuxt","rss"],"categories":["programming"],"cover_image":"/images/nuxt-content-rss-feed.jpg","excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you are a user of "},{"type":"element","tag":"a","props":{"href":"https://content.nuxt.com/","rel":["nofollow"]},"children":[{"type":"text","value":"Nuxt Content"}]},{"type":"text","value":" and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you are a user of "},{"type":"element","tag":"a","props":{"href":"https://content.nuxt.com/","rel":["nofollow"]},"children":[{"type":"text","value":"Nuxt Content"}]},{"type":"text","value":" and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application."}]},{"type":"element","tag":"h2","props":{"id":"preface"},"children":[{"type":"text","value":"Preface"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In version 2 of Nuxt, the community module, "},{"type":"element","tag":"a","props":{"href":"https://github.com/nuxt-community/feed-module","rel":["nofollow"]},"children":[{"type":"text","value":"nuxt-community/feed-module"}]},{"type":"text","value":" was a popular choice for adding an RSS feed to your website. However, there has been an unresolved "},{"type":"element","tag":"a","props":{"href":"https://github.com/nuxt-community/feed-module/issues/106","rel":["nofollow"]},"children":[{"type":"text","value":"open issue"}]},{"type":"text","value":" since April 1st, 2022 to add support for Nuxt v3. Thankfully, implementing this feature without a module is relatively straight forward."}]},{"type":"element","tag":"h2","props":{"id":"instructions"},"children":[{"type":"text","value":"Instructions"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, install the "},{"type":"element","tag":"a","props":{"href":"https://www.npmjs.com/package/feed","rel":["nofollow"]},"children":[{"type":"text","value":"feed"}]},{"type":"text","value":" library into your project:"}]},{"type":"element","tag":"pre","props":{"className":"language-shell shiki shiki-themes github-light","code":"npm i -D feed\n","language":"shell","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"npm"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" i"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -D"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" feed\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, create a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"server/"}]},{"type":"text","value":" folder in your project if it does not already exist, and create a file named "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"server/routes/atom.ts"}]},{"type":"text","value":"."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Here, we will leverage the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"feed"}]},{"type":"text","value":" library and construct an XML representation of our Nuxt content. As you can see, we first define our "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"feed"}]},{"type":"text","value":" with metadata associated with our RSS feed. This will be used by RSS readers to provide context to the end user. Then, we query our Nuxt content with "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"serverQueryContent"}]},{"type":"text","value":" and append a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"feed.addItem"}]},{"type":"text","value":" for each article."}]},{"type":"element","tag":"pre","props":{"className":"language-ts shiki shiki-themes github-light","code":"import { serverQueryContent } from '#content/server';\nimport { Feed } from 'feed';\n\nconst BASE_URL = \"https://mywebsite.com\"\nconst AUTHOR_NAME = \"Firstname Lastname\"\n\nexport default defineEventHandler(async (event) => {\n\n const feed = new Feed({\n title: \"My Title\",\n description: \"My Description\",\n id: BASE_URL,\n link: BASE_URL,\n language: \"en\",\n image: `${BASE_URL}/images/placeholder.png`,\n favicon: `${BASE_URL}/favicon.ico`,\n copyright: `All rights reserved ${new Date().getFullYear()}, ${AUTHOR_NAME}`,\n updated: new Date(),\n generator: \"Nuxt static site generation + Feed for Node.js\",\n feedLinks: {\n atom: `${BASE_URL}/atom`\n },\n author: {\n name: AUTHOR_NAME,\n }\n });\n\n const articles = await serverQueryContent(event).find();\n\n articles.forEach((article) => {\n feed.addItem({\n title: article.title ? article.title : \"Missing Title\",\n id: article._path,\n link: `${BASE_URL}${article._path}`,\n description: article.description,\n author: [\n {\n name: AUTHOR_NAME,\n },\n ],\n date: new Date(article.date),\n image: article.cover_image ? `${BASE_URL}/${article.cover_image}` : undefined\n });\n });\n\n return feed.atom1();\n});\n","language":"ts","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" { serverQueryContent } "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" '#content/server'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":";\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" { Feed } "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 'feed'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":";\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"https://mywebsite.com\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" AUTHOR_NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"Firstname Lastname\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"export"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" default"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" defineEventHandler"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"async"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"event"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"=>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" feed"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" Feed"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" title: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"My Title\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" description: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"My Description\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":12},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" id: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":13},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" link: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":14},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" language: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"en\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":15},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" image: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}/images/placeholder.png`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":16},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" favicon: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}/favicon.ico`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":17},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" copyright: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`All rights reserved ${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" Date"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"()."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"getFullYear"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"()"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}, ${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"AUTHOR_NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":18},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" updated: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" Date"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(),\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":19},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" generator: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Nuxt static site generation + Feed for Node.js\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":20},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" feedLinks: {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":21},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" atom: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}/atom`\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":22},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" },\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":23},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" author: {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":24},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" name: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"AUTHOR_NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":25},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" }\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":26},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":27},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":28},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" articles"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" await"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" serverQueryContent"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(event)."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"find"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"();\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":29},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":30},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" articles."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"forEach"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"article"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"=>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":31},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" feed."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"addItem"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":32},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" title: article.title "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"?"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" article.title "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":":"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"Missing Title\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":33},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" id: article._path,\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":34},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" link: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"article"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"_path"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":35},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" description: article.description,\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":36},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" author: [\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":37},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":38},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" name: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"AUTHOR_NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":39},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" },\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":40},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ],\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":41},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" date: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" Date"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(article.date),\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":42},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" image: article.cover_image "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"?"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" `${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}/${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"article"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"cover_image"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" :"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" undefined\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":43},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":44},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":45},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":46},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" return"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" feed."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"atom1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"();\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":47},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"});\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And that's just about it! Except, if you are statically generating your website with the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"nuxt generate"}]},{"type":"text","value":" command, you will need to configure this server-side route to be pre-rendered on site generation. This is as simple as adding a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"nitro"}]},{"type":"text","value":" "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"prerender"}]},{"type":"text","value":" definition in your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"nuxt.config.ts"}]},{"type":"text","value":" file, like so:"}]},{"type":"element","tag":"pre","props":{"className":"language-ts shiki shiki-themes github-light","code":"nitro: {\n prerender: {\n routes: ['/atom']\n }\n}\n","language":"ts","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"nitro"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" prerender"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" routes"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": ["}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/atom'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" }\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"}\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"bonus"},"children":[{"type":"text","value":"Bonus"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"You may also be interested in adding a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sitemap.xml"}]},{"type":"text","value":" to your website. This can be done in almost an identical fashion!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Install the dependency:"}]},{"type":"element","tag":"pre","props":{"className":"language-shell shiki shiki-themes github-light","code":"npm i -D sitemap\n","language":"shell","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"npm"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" i"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -D"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" sitemap\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Create a route at "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"server/routes/sitemap.xml.ts"}]},{"type":"text","value":":"}]},{"type":"element","tag":"pre","props":{"className":"language-ts shiki shiki-themes github-light","code":"import { serverQueryContent } from '#content/server';\nimport { SitemapStream, streamToPromise } from 'sitemap';\n\nexport default defineEventHandler(async (event) => {\n const articles = await serverQueryContent(event).find();\n\n const sitemap = new SitemapStream({ hostname: 'https://my-website.com/' });\n\n // Add non nuxt content endpoints here\n sitemap.write({ url: '/' });\n sitemap.write({ url: '/articles' });\n\n // Dynamically generate routes for Nuxt markdown content\n articles.forEach((article) => sitemap.write({ url: article._path, changefreq: 'monthly' }));\n sitemap.end();\n\n return (await streamToPromise(sitemap));\n});\n","language":"ts","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" { serverQueryContent } "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" '#content/server'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":";\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" { SitemapStream, streamToPromise } "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 'sitemap'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":";\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"export"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" default"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" defineEventHandler"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"async"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"event"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"=>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" articles"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" await"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" serverQueryContent"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(event)."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"find"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"();\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" sitemap"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" SitemapStream"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({ hostname: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'https://my-website.com/'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":" // Add non nuxt content endpoints here\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" sitemap."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"write"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({ url: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" sitemap."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"write"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({ url: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/articles'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":12},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":13},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":" // Dynamically generate routes for Nuxt markdown content\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":14},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" articles."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"forEach"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"article"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"=>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" sitemap."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"write"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({ url: article._path, changefreq: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'monthly'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" }));\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":15},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" sitemap."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"end"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"();\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":16},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":17},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" return"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"await"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" streamToPromise"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(sitemap));\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":18},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"});\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And add the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"prerender"}]},{"type":"text","value":" entry in your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"nuxt.config.ts"}]},{"type":"text","value":":"}]},{"type":"element","tag":"pre","props":{"className":"language-ts shiki shiki-themes github-light","code":"nitro: {\n prerender: {\n routes: ['/sitemap.xml', '/atom']\n }\n}\n","language":"ts","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"nitro"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" prerender"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" routes"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": ["}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/sitemap.xml'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/atom'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" }\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"}\n"}]}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"preface","depth":2,"text":"Preface"},{"id":"instructions","depth":2,"text":"Instructions"},{"id":"bonus","depth":2,"text":"Bonus"}]}},"_type":"markdown","_id":"content:articles:nuxt-content-rss-feed.md","_source":"content","_file":"articles/nuxt-content-rss-feed.md","_stem":"articles/nuxt-content-rss-feed","_extension":"md"} \ No newline at end of file +{"_path":"/articles/nuxt-content-rss-feed","_dir":"articles","_draft":false,"_partial":false,"_locale":"","title":"How To Add an RSS Feed to a Nuxt Website","description":"If you are a user of Nuxt Content and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application.","draft":false,"date":"2024-01-06","tags":["nuxt","rss"],"categories":["programming"],"cover_image":"/images/nuxt-content-rss-feed.jpg","excerpt":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you are a user of "},{"type":"element","tag":"a","props":{"href":"https://content.nuxt.com/","rel":["nofollow"]},"children":[{"type":"text","value":"Nuxt Content"}]},{"type":"text","value":" and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application."}]}]},"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If you are a user of "},{"type":"element","tag":"a","props":{"href":"https://content.nuxt.com/","rel":["nofollow"]},"children":[{"type":"text","value":"Nuxt Content"}]},{"type":"text","value":" and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application."}]},{"type":"element","tag":"h2","props":{"id":"preface"},"children":[{"type":"text","value":"Preface"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"In version 2 of Nuxt, the community module, "},{"type":"element","tag":"a","props":{"href":"https://github.com/nuxt-community/feed-module","rel":["nofollow"]},"children":[{"type":"text","value":"nuxt-community/feed-module"}]},{"type":"text","value":" was a popular choice for adding an RSS feed to your website. However, there has been an unresolved "},{"type":"element","tag":"a","props":{"href":"https://github.com/nuxt-community/feed-module/issues/106","rel":["nofollow"]},"children":[{"type":"text","value":"open issue"}]},{"type":"text","value":" since April 1st, 2022 to add support for Nuxt v3. Thankfully, implementing this feature without a module is relatively straight forward."}]},{"type":"element","tag":"h2","props":{"id":"instructions"},"children":[{"type":"text","value":"Instructions"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First, install the "},{"type":"element","tag":"a","props":{"href":"https://www.npmjs.com/package/feed","rel":["nofollow"]},"children":[{"type":"text","value":"feed"}]},{"type":"text","value":" library into your project:"}]},{"type":"element","tag":"pre","props":{"className":"language-shell shiki shiki-themes github-light","code":"npm i -D feed\n","language":"shell","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"npm"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" i"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -D"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" feed\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Then, create a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"server/"}]},{"type":"text","value":" folder in your project if it does not already exist, and create a file named "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"server/routes/atom.ts"}]},{"type":"text","value":"."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Here, we will leverage the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"feed"}]},{"type":"text","value":" library and construct an XML representation of our Nuxt content. As you can see, we first define our "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"feed"}]},{"type":"text","value":" with metadata associated with our RSS feed. This will be used by RSS readers to provide context to the end user. Then, we query our Nuxt content with "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"serverQueryContent"}]},{"type":"text","value":" and append a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"feed.addItem"}]},{"type":"text","value":" for each article."}]},{"type":"element","tag":"pre","props":{"className":"language-ts shiki shiki-themes github-light","code":"import { serverQueryContent } from '#content/server';\nimport { Feed } from 'feed';\n\nconst BASE_URL = \"https://mywebsite.com\"\nconst AUTHOR_NAME = \"Firstname Lastname\"\n\nexport default defineEventHandler(async (event) => {\n\n const feed = new Feed({\n title: \"My Title\",\n description: \"My Description\",\n id: BASE_URL,\n link: BASE_URL,\n language: \"en\",\n image: `${BASE_URL}/images/placeholder.png`,\n favicon: `${BASE_URL}/favicon.ico`,\n copyright: `All rights reserved ${new Date().getFullYear()}, ${AUTHOR_NAME}`,\n updated: new Date(),\n generator: \"Nuxt static site generation + Feed for Node.js\",\n feedLinks: {\n atom: `${BASE_URL}/atom`\n },\n author: {\n name: AUTHOR_NAME,\n }\n });\n\n const articles = await serverQueryContent(event).find();\n\n articles.forEach((article) => {\n feed.addItem({\n title: article.title ? article.title : \"Missing Title\",\n id: article._path,\n link: `${BASE_URL}${article._path}`,\n description: article.description,\n author: [\n {\n name: AUTHOR_NAME,\n },\n ],\n date: new Date(article.date),\n image: article.cover_image ? `${BASE_URL}/${article.cover_image}` : undefined\n });\n });\n\n return feed.atom1();\n});\n","language":"ts","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" { serverQueryContent } "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" '#content/server'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":";\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" { Feed } "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 'feed'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":";\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"https://mywebsite.com\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" AUTHOR_NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"Firstname Lastname\"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"export"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" default"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" defineEventHandler"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"async"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"event"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"=>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" feed"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" Feed"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" title: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"My Title\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" description: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"My Description\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":12},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" id: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":13},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" link: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":14},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" language: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"en\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":15},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" image: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}/images/placeholder.png`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":16},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" favicon: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}/favicon.ico`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":17},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" copyright: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`All rights reserved ${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" Date"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"()."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"getFullYear"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"()"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}, ${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"AUTHOR_NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":18},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" updated: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" Date"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(),\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":19},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" generator: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"\"Nuxt static site generation + Feed for Node.js\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":20},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" feedLinks: {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":21},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" atom: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}/atom`\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":22},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" },\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":23},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" author: {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":24},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" name: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"AUTHOR_NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":25},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" }\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":26},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":27},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":28},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" articles"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" await"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" serverQueryContent"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(event)."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"find"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"();\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":29},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":30},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" articles."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"forEach"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"article"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"=>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":31},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" feed."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"addItem"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":32},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" title: article.title "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"?"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" article.title "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":":"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" \"Missing Title\""}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":33},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" id: article._path,\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":34},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" link: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"`${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"article"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"_path"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":35},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" description: article.description,\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":36},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" author: [\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":37},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":38},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" name: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"AUTHOR_NAME"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":",\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":39},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" },\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":40},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ],\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":41},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" date: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" Date"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(article.date),\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":42},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" image: article.cover_image "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"?"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" `${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":"BASE_URL"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}/${"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"article"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"cover_image"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"}`"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" :"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" undefined\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":43},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":44},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":45},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":46},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" return"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" feed."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"atom1"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"();\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":47},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"});\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And that's just about it! Except, if you are statically generating your website with the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"nuxt generate"}]},{"type":"text","value":" command, you will need to configure this server-side route to be pre-rendered on site generation. This is as simple as adding a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"nitro"}]},{"type":"text","value":" "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"prerender"}]},{"type":"text","value":" definition in your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"nuxt.config.ts"}]},{"type":"text","value":" file, like so:"}]},{"type":"element","tag":"pre","props":{"className":"language-ts shiki shiki-themes github-light","code":"nitro: {\n prerender: {\n routes: ['/atom']\n }\n}\n","language":"ts","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"nitro"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" prerender"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" routes"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": ["}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/atom'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" }\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"}\n"}]}]}]}]},{"type":"element","tag":"h2","props":{"id":"bonus"},"children":[{"type":"text","value":"Bonus"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"You may also be interested in adding a "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"sitemap.xml"}]},{"type":"text","value":" to your website. This can be done in almost an identical fashion!"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Install the dependency:"}]},{"type":"element","tag":"pre","props":{"className":"language-shell shiki shiki-themes github-light","code":"npm i -D sitemap\n","language":"shell","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"npm"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" i"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" -D"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" sitemap\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Create a route at "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"server/routes/sitemap.xml.ts"}]},{"type":"text","value":":"}]},{"type":"element","tag":"pre","props":{"className":"language-ts shiki shiki-themes github-light","code":"import { serverQueryContent } from '#content/server';\nimport { SitemapStream, streamToPromise } from 'sitemap';\n\nexport default defineEventHandler(async (event) => {\n const articles = await serverQueryContent(event).find();\n\n const sitemap = new SitemapStream({ hostname: 'https://my-website.com/' });\n\n // Add non nuxt content endpoints here\n sitemap.write({ url: '/' });\n sitemap.write({ url: '/articles' });\n\n // Dynamically generate routes for Nuxt markdown content\n articles.forEach((article) => sitemap.write({ url: article._path, changefreq: 'monthly' }));\n sitemap.end();\n\n return (await streamToPromise(sitemap));\n});\n","language":"ts","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" { serverQueryContent } "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" '#content/server'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":";\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"import"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" { SitemapStream, streamToPromise } "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"from"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":" 'sitemap'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":";\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"export"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" default"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" defineEventHandler"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"async"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"event"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"=>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" articles"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" await"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" serverQueryContent"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(event)."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"find"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"();\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":6},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":7},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" const"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#005CC5"},"children":[{"type":"text","value":" sitemap"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" ="}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" new"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" SitemapStream"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({ hostname: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'https://my-website.com/'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":8},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":9},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":" // Add non nuxt content endpoints here\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":10},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" sitemap."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"write"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({ url: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":11},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" sitemap."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"write"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({ url: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/articles'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" });\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":12},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":13},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6A737D"},"children":[{"type":"text","value":" // Dynamically generate routes for Nuxt markdown content\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":14},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" articles."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"forEach"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#E36209"},"children":[{"type":"text","value":"article"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":") "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"=>"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" sitemap."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"write"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"({ url: article._path, changefreq: "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'monthly'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" }));\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":15},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" sitemap."}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"end"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"();\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":16},"children":[{"type":"element","tag":"span","props":{"emptyLinePlaceholder":true},"children":[{"type":"text","value":"\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":17},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":" return"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" ("}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#D73A49"},"children":[{"type":"text","value":"await"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" streamToPromise"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"(sitemap));\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":18},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"});\n"}]}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"And add the "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"prerender"}]},{"type":"text","value":" entry in your "},{"type":"element","tag":"code","props":{"className":[]},"children":[{"type":"text","value":"nuxt.config.ts"}]},{"type":"text","value":":"}]},{"type":"element","tag":"pre","props":{"className":"language-ts shiki shiki-themes github-light","code":"nitro: {\n prerender: {\n routes: ['/sitemap.xml', '/atom']\n }\n}\n","language":"ts","meta":"","style":""},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"element","tag":"span","props":{"class":"line","line":1},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":"nitro"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":2},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" prerender"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": {\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":3},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#6F42C1"},"children":[{"type":"text","value":" routes"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":": ["}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/sitemap.xml'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":", "}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#032F62"},"children":[{"type":"text","value":"'/atom'"}]},{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"]\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":4},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":" }\n"}]}]},{"type":"element","tag":"span","props":{"class":"line","line":5},"children":[{"type":"element","tag":"span","props":{"style":"--shiki-default:#24292E"},"children":[{"type":"text","value":"}\n"}]}]}]}]},{"type":"element","tag":"style","props":{},"children":[{"type":"text","value":"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}"}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"preface","depth":2,"text":"Preface"},{"id":"instructions","depth":2,"text":"Instructions"},{"id":"bonus","depth":2,"text":"Bonus"}]}},"_type":"markdown","_id":"content:articles:nuxt-content-rss-feed.md","_source":"content","_file":"articles/nuxt-content-rss-feed.md","_extension":"md"} \ No newline at end of file diff --git a/articles/_payload.json b/articles/_payload.json index 268203a8..7d780160 100644 --- a/articles/_payload.json +++ b/articles/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":360},["Reactive",2],{"articles":3},[4,45,87,131,157,174,207,222,239,253,277,297,313,329],{"_path":5,"title":6,"description":7,"date":8,"tags":9,"categories":12,"excerpt":15,"_id":44},"/articles/ssh-ed25519-sk-yubikey","Configuring a YubiKey for use with OpenSSH","YubiKey's are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" ed25519-sk key type that supports FIDO compliant hardware keys.","2024-06-09",[10,11],"unix","configurations",[13,14],"tooling","tips",{"type":16,"children":17},"root",[18],{"type":19,"tag":20,"props":21,"children":22},"element","p",{},[23,33,35,42],{"type":19,"tag":24,"props":25,"children":29},"a",{"href":26,"rel":27},"https://www.yubico.com/",[28],"nofollow",[30],{"type":31,"value":32},"text","YubiKey's",{"type":31,"value":34}," are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" ",{"type":19,"tag":36,"props":37,"children":39},"code",{"className":38},[],[40],{"type":31,"value":41},"ed25519-sk",{"type":31,"value":43}," key type that supports FIDO compliant hardware keys.","content:articles:ssh-ed25519-sk-yubikey.md",{"_path":46,"title":47,"description":48,"date":49,"tags":50,"categories":53,"excerpt":54,"_id":86},"/articles/vim-fugitive-gpg-pinentry","Using pinentry-mac to sign commits from vim-fugitive","In order to sign git commits from within Vim using a plugin like tpope/vim-fugitive, it is necessary to configure the gpg-agent to use a GUI based pinentry-program.","2024-05-11",[51,52],"vim","tip",[13,14],{"type":16,"children":55},[56],{"type":19,"tag":20,"props":57,"children":58},{},[59,61,68,70,76,78,84],{"type":31,"value":60},"In order to sign git commits from within Vim using a plugin like ",{"type":19,"tag":24,"props":62,"children":65},{"href":63,"rel":64},"https://github.com/tpope/vim-fugitive",[28],[66],{"type":31,"value":67},"tpope/vim-fugitive",{"type":31,"value":69},", it is necessary to configure the ",{"type":19,"tag":36,"props":71,"children":73},{"className":72},[],[74],{"type":31,"value":75},"gpg-agent",{"type":31,"value":77}," to use a GUI based ",{"type":19,"tag":36,"props":79,"children":81},{"className":80},[],[82],{"type":31,"value":83},"pinentry-program",{"type":31,"value":85},".","content:articles:vim-fugitive-gpg-pinentry.md",{"_path":88,"title":89,"description":90,"date":91,"tags":92,"categories":95,"excerpt":97,"_id":130},"/articles/podcast-transcription-whispercpp","Easily Transcribe Podcasts with Whisper.cpp","If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive whisper.cpp project. This high-performance fork of OpenAI's Whisper can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the Alter Everything podcast.","2024-01-08",[93,94],"whisper.cpp","ml",[96],"programming",{"type":16,"children":98},[99],{"type":19,"tag":20,"props":100,"children":101},{},[102,104,110,112,119,121,128],{"type":31,"value":103},"If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive ",{"type":19,"tag":24,"props":105,"children":108},{"href":106,"rel":107},"https://github.com/ggerganov/whisper.cpp",[28],[109],{"type":31,"value":93},{"type":31,"value":111}," project. This high-performance fork of ",{"type":19,"tag":24,"props":113,"children":116},{"href":114,"rel":115},"https://github.com/openai/whisper",[28],[117],{"type":31,"value":118},"OpenAI's Whisper",{"type":31,"value":120}," can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the ",{"type":19,"tag":24,"props":122,"children":125},{"href":123,"rel":124},"https://podcasts.apple.com/us/podcast/alter-everything/id1356137854",[28],[126],{"type":31,"value":127},"Alter Everything",{"type":31,"value":129}," podcast.","content:articles:podcast-transcription-whispercpp.md",{"_path":132,"title":133,"description":134,"date":135,"tags":136,"categories":139,"excerpt":140,"_id":156},"/articles/nuxt-content-rss-feed","How To Add an RSS Feed to a Nuxt Website","If you are a user of Nuxt Content and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application.","2024-01-06",[137,138],"nuxt","rss",[96],{"type":16,"children":141},[142],{"type":19,"tag":20,"props":143,"children":144},{},[145,147,154],{"type":31,"value":146},"If you are a user of ",{"type":19,"tag":24,"props":148,"children":151},{"href":149,"rel":150},"https://content.nuxt.com/",[28],[152],{"type":31,"value":153},"Nuxt Content",{"type":31,"value":155}," and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application.","content:articles:nuxt-content-rss-feed.md",{"_path":158,"title":159,"description":160,"date":161,"tags":162,"categories":166,"excerpt":167,"_id":173},"/articles/fennel-initial-exploration","Impressions of Fennel with Hammerspoon","A while back I read an introductory book on Lisp programming titled, \"The Little\nSchemer\". This book opened my mind to new (to me) programming paradigms, and left me\nwith a strong desire to find a way to incorporate Lisp programming into my every day\nlife. It took some time, but I believe I've found what I've been looking for: Fennel.","2023-10-22",[163,164,165],"lisp","hammerspoon","fennel",[163],{"type":16,"children":168},[169],{"type":19,"tag":20,"props":170,"children":171},{},[172],{"type":31,"value":160},"content:articles:fennel-initial-exploration.md",{"_path":175,"title":176,"description":177,"date":178,"tags":179,"categories":182,"excerpt":183,"_id":206},"/articles/doctl","Exploring the Digital Ocean `doctl` Utility","I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean doctl command line utility.\nThis proved to be an extremely easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future.","2023-01-01",[180,181],"linux","digital-ocean",[180],{"type":16,"children":184},[185],{"type":19,"tag":20,"props":186,"children":187},{},[188,190,196,198,204],{"type":31,"value":189},"I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean ",{"type":19,"tag":36,"props":191,"children":193},{"className":192},[],[194],{"type":31,"value":195},"doctl",{"type":31,"value":197}," command line utility.\nThis proved to be an ",{"type":19,"tag":199,"props":200,"children":201},"em",{},[202],{"type":31,"value":203},"extremely",{"type":31,"value":205}," easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future.","content:articles:doctl.md",{"_path":208,"title":209,"description":210,"date":211,"tags":212,"categories":213,"excerpt":215,"_id":221},"/articles/nuxt-v3-migration","This Website Has Been Migrated to Nuxt 3 🎉","This website has been migrated to the latest version of the Nuxt web framework, and with it comes all of the exciting goodies that the Vue and Nuxt teams have been concocting over the past few years.\nNot to mention, all of the great plugins in the Vue ecosystem!","2022-12-31",[137],[214],"web",{"type":16,"children":216},[217],{"type":19,"tag":20,"props":218,"children":219},{},[220],{"type":31,"value":210},"content:articles:nuxt-v3-migration.md",{"_path":223,"title":224,"description":225,"date":226,"tags":227,"categories":231,"excerpt":232,"_id":238},"/articles/migrate-truenas-from-core-to-scale","Migrate to TrueNAS Scale from TrueNAS Core","TrueNAS Scale offers a variety of interesting features that are not supported in its TrueNAS Core counterpart. Most notably, because the base operating system is Debian Linux, opposed to FreeBSD, there is native support for Linux containers via Docker, and Kubernetes Pods! This post walks through the steps required to upgrade from TrueNAS Core to TrueNAS Scale.","2021-12-28",[228,229,230],"homelab","supermicro","truenas",[228],{"type":16,"children":233},[234],{"type":19,"tag":20,"props":235,"children":236},{},[237],{"type":31,"value":225},"content:articles:migrate-truenas-from-core-to-scale.md",{"_path":240,"title":241,"description":242,"date":243,"tags":244,"categories":245,"excerpt":246,"_id":252},"/articles/reset-ipmi-password-from-host-os","Reset IPMI Credentials from the Host OS","If you ever find yourself locked out of the Intelligent Platform Management Interface (IPMI) of a server, these\ninstructions will guide your through the process of resetting the credentials to their default values from the host\noperating system.","2021-12-27",[228,229,230],[228],{"type":16,"children":247},[248],{"type":19,"tag":20,"props":249,"children":250},{},[251],{"type":31,"value":242},"content:articles:reset-ipmi-password-from-host-os.md",{"_path":254,"title":255,"description":256,"date":257,"tags":258,"categories":260,"excerpt":261,"_id":276},"/articles/quick-tip-rerunning-bash-commands","Tip: Re-running Bash Commands","Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use sudo for a command that requires\nroot privileges.","2021-09-22",[52,259],"bash",[14],{"type":16,"children":262},[263],{"type":19,"tag":20,"props":264,"children":265},{},[266,268,274],{"type":31,"value":267},"Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use ",{"type":19,"tag":36,"props":269,"children":271},{"className":270},[],[272],{"type":31,"value":273},"sudo",{"type":31,"value":275}," for a command that requires\nroot privileges.","content:articles:quick-tip-rerunning-bash-commands.md",{"_path":278,"title":279,"description":280,"date":281,"tags":282,"categories":287,"excerpt":290,"_id":296},"/articles/unit-testing-micropython-with-mocks","Unit Testing in MicroPython with Mocks","Unit testing code for embedded systems can be challenging. While it's possible\nto leverage emulators, write side-effect free code, or run tests on the\nhardware itself, it's often easiest to unit test the code on your personal\ncomputer with mocked hardware functionality.","2020-02-07",[283,284,285,286],"micropython","testing","mocks","tutorial",[288,289],"python","embedded",{"type":16,"children":291},[292],{"type":19,"tag":20,"props":293,"children":294},{},[295],{"type":31,"value":280},"content:articles:unit-testing-micropython-with-mocks.md",{"_path":298,"title":299,"description":300,"date":301,"tags":302,"categories":305,"excerpt":306,"_id":312},"/articles/persistent-archlinux-usb","Create a Persistent Arch Linux Bootable USB with Vagrant","When installing a linux distribution, it is common for the instructions to have\nthe user create a bootable USB, boot from the device, and proceed with the\ninstallation procedure from that live medium. However, this blog post will\noutline an alternative approach where a virtual machine created with Vagrant\nwill be used in favor of the live medium.","2020-01-09",[303,304],"vagrant","archlinux",[180],{"type":16,"children":307},[308],{"type":19,"tag":20,"props":309,"children":310},{},[311],{"type":31,"value":300},"content:articles:persistent-archlinux-usb.md",{"_path":314,"title":315,"description":316,"date":317,"tags":318,"categories":321,"excerpt":322,"_id":328},"/articles/docker-selinux-volumes","Docker Volume Permissions with SELinux","Unfamiliar with running Docker on a SELinux enabled system, I found myself\nrunning into a bunch of file permission errors while creating volumes.","2019-12-26",[319,320],"docker","selinux",[180],{"type":16,"children":323},[324],{"type":19,"tag":20,"props":325,"children":326},{},[327],{"type":31,"value":316},"content:articles:docker-selinux-volumes.md",{"_path":330,"title":331,"description":332,"date":333,"tags":334,"categories":337,"excerpt":338,"_id":359},"/articles/apu2-firmware-upgrade","Upgrading the Firmware on the PCEngines APU2","I've had a PCEngines APU2 gathering dust for a\nfew years, and have recently decided to dust it off.","2019-12-21",[335,336],"pcengine","apu",[180],{"type":16,"children":339},[340,354],{"type":19,"tag":20,"props":341,"children":342},{},[343,345,352],{"type":31,"value":344},"I've had a ",{"type":19,"tag":24,"props":346,"children":349},{"href":347,"rel":348},"https://pcengines.ch/apu2.htm",[28],[350],{"type":31,"value":351},"PCEngines APU2",{"type":31,"value":353}," gathering dust for a\nfew years, and have recently decided to dust it off.",{"type":19,"tag":20,"props":355,"children":356},{},[357],{"type":31,"value":358},"Since the last time the device has been powered on, there have been many great\nimprovements to the firmware, and it was very-much due for an upgrade. The\nfollowing steps outline how the firmware was upgraded on the APU from the\nalready-installed operating system -- CentOS.","content:articles:apu2-firmware-upgrade.md",1726174738536] \ No newline at end of file +[{"data":1,"prerenderedAt":360},["Reactive",2],{"articles":3},[4,45,87,131,157,174,207,222,239,253,277,297,313,329],{"_path":5,"title":6,"description":7,"date":8,"tags":9,"categories":12,"excerpt":15,"_id":44},"/articles/ssh-ed25519-sk-yubikey","Configuring a YubiKey for use with OpenSSH","YubiKey's are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" ed25519-sk key type that supports FIDO compliant hardware keys.","2024-06-09",[10,11],"unix","configurations",[13,14],"tooling","tips",{"type":16,"children":17},"root",[18],{"type":19,"tag":20,"props":21,"children":22},"element","p",{},[23,33,35,42],{"type":19,"tag":24,"props":25,"children":29},"a",{"href":26,"rel":27},"https://www.yubico.com/",[28],"nofollow",[30],{"type":31,"value":32},"text","YubiKey's",{"type":31,"value":34}," are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" ",{"type":19,"tag":36,"props":37,"children":39},"code",{"className":38},[],[40],{"type":31,"value":41},"ed25519-sk",{"type":31,"value":43}," key type that supports FIDO compliant hardware keys.","content:articles:ssh-ed25519-sk-yubikey.md",{"_path":46,"title":47,"description":48,"date":49,"tags":50,"categories":53,"excerpt":54,"_id":86},"/articles/vim-fugitive-gpg-pinentry","Using pinentry-mac to sign commits from vim-fugitive","In order to sign git commits from within Vim using a plugin like tpope/vim-fugitive, it is necessary to configure the gpg-agent to use a GUI based pinentry-program.","2024-05-11",[51,52],"vim","tip",[13,14],{"type":16,"children":55},[56],{"type":19,"tag":20,"props":57,"children":58},{},[59,61,68,70,76,78,84],{"type":31,"value":60},"In order to sign git commits from within Vim using a plugin like ",{"type":19,"tag":24,"props":62,"children":65},{"href":63,"rel":64},"https://github.com/tpope/vim-fugitive",[28],[66],{"type":31,"value":67},"tpope/vim-fugitive",{"type":31,"value":69},", it is necessary to configure the ",{"type":19,"tag":36,"props":71,"children":73},{"className":72},[],[74],{"type":31,"value":75},"gpg-agent",{"type":31,"value":77}," to use a GUI based ",{"type":19,"tag":36,"props":79,"children":81},{"className":80},[],[82],{"type":31,"value":83},"pinentry-program",{"type":31,"value":85},".","content:articles:vim-fugitive-gpg-pinentry.md",{"_path":88,"title":89,"description":90,"date":91,"tags":92,"categories":95,"excerpt":97,"_id":130},"/articles/podcast-transcription-whispercpp","Easily Transcribe Podcasts with Whisper.cpp","If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive whisper.cpp project. This high-performance fork of OpenAI's Whisper can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the Alter Everything podcast.","2024-01-08",[93,94],"whisper.cpp","ml",[96],"programming",{"type":16,"children":98},[99],{"type":19,"tag":20,"props":100,"children":101},{},[102,104,110,112,119,121,128],{"type":31,"value":103},"If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive ",{"type":19,"tag":24,"props":105,"children":108},{"href":106,"rel":107},"https://github.com/ggerganov/whisper.cpp",[28],[109],{"type":31,"value":93},{"type":31,"value":111}," project. This high-performance fork of ",{"type":19,"tag":24,"props":113,"children":116},{"href":114,"rel":115},"https://github.com/openai/whisper",[28],[117],{"type":31,"value":118},"OpenAI's Whisper",{"type":31,"value":120}," can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the ",{"type":19,"tag":24,"props":122,"children":125},{"href":123,"rel":124},"https://podcasts.apple.com/us/podcast/alter-everything/id1356137854",[28],[126],{"type":31,"value":127},"Alter Everything",{"type":31,"value":129}," podcast.","content:articles:podcast-transcription-whispercpp.md",{"_path":132,"title":133,"description":134,"date":135,"tags":136,"categories":139,"excerpt":140,"_id":156},"/articles/nuxt-content-rss-feed","How To Add an RSS Feed to a Nuxt Website","If you are a user of Nuxt Content and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application.","2024-01-06",[137,138],"nuxt","rss",[96],{"type":16,"children":141},[142],{"type":19,"tag":20,"props":143,"children":144},{},[145,147,154],{"type":31,"value":146},"If you are a user of ",{"type":19,"tag":24,"props":148,"children":151},{"href":149,"rel":150},"https://content.nuxt.com/",[28],[152],{"type":31,"value":153},"Nuxt Content",{"type":31,"value":155}," and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application.","content:articles:nuxt-content-rss-feed.md",{"_path":158,"title":159,"description":160,"date":161,"tags":162,"categories":166,"excerpt":167,"_id":173},"/articles/fennel-initial-exploration","Impressions of Fennel with Hammerspoon","A while back I read an introductory book on Lisp programming titled, \"The Little\nSchemer\". This book opened my mind to new (to me) programming paradigms, and left me\nwith a strong desire to find a way to incorporate Lisp programming into my every day\nlife. It took some time, but I believe I've found what I've been looking for: Fennel.","2023-10-22",[163,164,165],"lisp","hammerspoon","fennel",[163],{"type":16,"children":168},[169],{"type":19,"tag":20,"props":170,"children":171},{},[172],{"type":31,"value":160},"content:articles:fennel-initial-exploration.md",{"_path":175,"title":176,"description":177,"date":178,"tags":179,"categories":182,"excerpt":183,"_id":206},"/articles/doctl","Exploring the Digital Ocean `doctl` Utility","I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean doctl command line utility.\nThis proved to be an extremely easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future.","2023-01-01",[180,181],"linux","digital-ocean",[180],{"type":16,"children":184},[185],{"type":19,"tag":20,"props":186,"children":187},{},[188,190,196,198,204],{"type":31,"value":189},"I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean ",{"type":19,"tag":36,"props":191,"children":193},{"className":192},[],[194],{"type":31,"value":195},"doctl",{"type":31,"value":197}," command line utility.\nThis proved to be an ",{"type":19,"tag":199,"props":200,"children":201},"em",{},[202],{"type":31,"value":203},"extremely",{"type":31,"value":205}," easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future.","content:articles:doctl.md",{"_path":208,"title":209,"description":210,"date":211,"tags":212,"categories":213,"excerpt":215,"_id":221},"/articles/nuxt-v3-migration","This Website Has Been Migrated to Nuxt 3 🎉","This website has been migrated to the latest version of the Nuxt web framework, and with it comes all of the exciting goodies that the Vue and Nuxt teams have been concocting over the past few years.\nNot to mention, all of the great plugins in the Vue ecosystem!","2022-12-31",[137],[214],"web",{"type":16,"children":216},[217],{"type":19,"tag":20,"props":218,"children":219},{},[220],{"type":31,"value":210},"content:articles:nuxt-v3-migration.md",{"_path":223,"title":224,"description":225,"date":226,"tags":227,"categories":231,"excerpt":232,"_id":238},"/articles/migrate-truenas-from-core-to-scale","Migrate to TrueNAS Scale from TrueNAS Core","TrueNAS Scale offers a variety of interesting features that are not supported in its TrueNAS Core counterpart. Most notably, because the base operating system is Debian Linux, opposed to FreeBSD, there is native support for Linux containers via Docker, and Kubernetes Pods! This post walks through the steps required to upgrade from TrueNAS Core to TrueNAS Scale.","2021-12-28",[228,229,230],"homelab","supermicro","truenas",[228],{"type":16,"children":233},[234],{"type":19,"tag":20,"props":235,"children":236},{},[237],{"type":31,"value":225},"content:articles:migrate-truenas-from-core-to-scale.md",{"_path":240,"title":241,"description":242,"date":243,"tags":244,"categories":245,"excerpt":246,"_id":252},"/articles/reset-ipmi-password-from-host-os","Reset IPMI Credentials from the Host OS","If you ever find yourself locked out of the Intelligent Platform Management Interface (IPMI) of a server, these\ninstructions will guide your through the process of resetting the credentials to their default values from the host\noperating system.","2021-12-27",[228,229,230],[228],{"type":16,"children":247},[248],{"type":19,"tag":20,"props":249,"children":250},{},[251],{"type":31,"value":242},"content:articles:reset-ipmi-password-from-host-os.md",{"_path":254,"title":255,"description":256,"date":257,"tags":258,"categories":260,"excerpt":261,"_id":276},"/articles/quick-tip-rerunning-bash-commands","Tip: Re-running Bash Commands","Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use sudo for a command that requires\nroot privileges.","2021-09-22",[52,259],"bash",[14],{"type":16,"children":262},[263],{"type":19,"tag":20,"props":264,"children":265},{},[266,268,274],{"type":31,"value":267},"Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use ",{"type":19,"tag":36,"props":269,"children":271},{"className":270},[],[272],{"type":31,"value":273},"sudo",{"type":31,"value":275}," for a command that requires\nroot privileges.","content:articles:quick-tip-rerunning-bash-commands.md",{"_path":278,"title":279,"description":280,"date":281,"tags":282,"categories":287,"excerpt":290,"_id":296},"/articles/unit-testing-micropython-with-mocks","Unit Testing in MicroPython with Mocks","Unit testing code for embedded systems can be challenging. While it's possible\nto leverage emulators, write side-effect free code, or run tests on the\nhardware itself, it's often easiest to unit test the code on your personal\ncomputer with mocked hardware functionality.","2020-02-07",[283,284,285,286],"micropython","testing","mocks","tutorial",[288,289],"python","embedded",{"type":16,"children":291},[292],{"type":19,"tag":20,"props":293,"children":294},{},[295],{"type":31,"value":280},"content:articles:unit-testing-micropython-with-mocks.md",{"_path":298,"title":299,"description":300,"date":301,"tags":302,"categories":305,"excerpt":306,"_id":312},"/articles/persistent-archlinux-usb","Create a Persistent Arch Linux Bootable USB with Vagrant","When installing a linux distribution, it is common for the instructions to have\nthe user create a bootable USB, boot from the device, and proceed with the\ninstallation procedure from that live medium. However, this blog post will\noutline an alternative approach where a virtual machine created with Vagrant\nwill be used in favor of the live medium.","2020-01-09",[303,304],"vagrant","archlinux",[180],{"type":16,"children":307},[308],{"type":19,"tag":20,"props":309,"children":310},{},[311],{"type":31,"value":300},"content:articles:persistent-archlinux-usb.md",{"_path":314,"title":315,"description":316,"date":317,"tags":318,"categories":321,"excerpt":322,"_id":328},"/articles/docker-selinux-volumes","Docker Volume Permissions with SELinux","Unfamiliar with running Docker on a SELinux enabled system, I found myself\nrunning into a bunch of file permission errors while creating volumes.","2019-12-26",[319,320],"docker","selinux",[180],{"type":16,"children":323},[324],{"type":19,"tag":20,"props":325,"children":326},{},[327],{"type":31,"value":316},"content:articles:docker-selinux-volumes.md",{"_path":330,"title":331,"description":332,"date":333,"tags":334,"categories":337,"excerpt":338,"_id":359},"/articles/apu2-firmware-upgrade","Upgrading the Firmware on the PCEngines APU2","I've had a PCEngines APU2 gathering dust for a\nfew years, and have recently decided to dust it off.","2019-12-21",[335,336],"pcengine","apu",[180],{"type":16,"children":339},[340,354],{"type":19,"tag":20,"props":341,"children":342},{},[343,345,352],{"type":31,"value":344},"I've had a ",{"type":19,"tag":24,"props":346,"children":349},{"href":347,"rel":348},"https://pcengines.ch/apu2.htm",[28],[350],{"type":31,"value":351},"PCEngines APU2",{"type":31,"value":353}," gathering dust for a\nfew years, and have recently decided to dust it off.",{"type":19,"tag":20,"props":355,"children":356},{},[357],{"type":31,"value":358},"Since the last time the device has been powered on, there have been many great\nimprovements to the firmware, and it was very-much due for an upgrade. The\nfollowing steps outline how the firmware was upgraded on the APU from the\nalready-installed operating system -- CentOS.","content:articles:apu2-firmware-upgrade.md",1727638396943] \ No newline at end of file diff --git a/articles/apu2-firmware-upgrade/_payload.json b/articles/apu2-firmware-upgrade/_payload.json index 19e06d5e..cffe9481 100644 --- a/articles/apu2-firmware-upgrade/_payload.json +++ b/articles/apu2-firmware-upgrade/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":315},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"draft":6,"tags":11,"categories":14,"excerpt":16,"body":43,"_type":309,"_id":310,"_source":311,"_file":312,"_stem":313,"_extension":314},"/articles/apu2-firmware-upgrade","articles",false,"","Upgrading the Firmware on the PCEngines APU2","I've had a PCEngines APU2 gathering dust for a\nfew years, and have recently decided to dust it off.","2019-12-21",[12,13],"pcengine","apu",[15],"linux",{"type":17,"children":18},"root",[19,38],{"type":20,"tag":21,"props":22,"children":23},"element","p",{},[24,27,36],{"type":25,"value":26},"text","I've had a ",{"type":20,"tag":28,"props":29,"children":33},"a",{"href":30,"rel":31},"https://pcengines.ch/apu2.htm",[32],"nofollow",[34],{"type":25,"value":35},"PCEngines APU2",{"type":25,"value":37}," gathering dust for a\nfew years, and have recently decided to dust it off.",{"type":20,"tag":21,"props":39,"children":40},{},[41],{"type":25,"value":42},"Since the last time the device has been powered on, there have been many great\nimprovements to the firmware, and it was very-much due for an upgrade. The\nfollowing steps outline how the firmware was upgraded on the APU from the\nalready-installed operating system -- CentOS.",{"type":17,"children":44,"toc":307},[45,55,59,64,74,103,161,174,200,205,244,253,301],{"type":20,"tag":21,"props":46,"children":47},{},[48,49,54],{"type":25,"value":26},{"type":20,"tag":28,"props":50,"children":52},{"href":30,"rel":51},[32],[53],{"type":25,"value":35},{"type":25,"value":37},{"type":20,"tag":21,"props":56,"children":57},{},[58],{"type":25,"value":42},{"type":20,"tag":21,"props":60,"children":61},{},[62],{"type":25,"value":63},"First, we will connect to the device over the serial port",{"type":20,"tag":65,"props":66,"children":68},"pre",{"code":67},"screen /dev/tty.usbserial 115200\n",[69],{"type":20,"tag":70,"props":71,"children":72},"code",{"__ignoreMap":7},[73],{"type":25,"value":67},{"type":20,"tag":21,"props":75,"children":76},{},[77,79,85,87,93,95,101],{"type":25,"value":78},"Then, we will install the ",{"type":20,"tag":70,"props":80,"children":82},{"className":81},[],[83],{"type":25,"value":84},"flashrom",{"type":25,"value":86}," utility that is needed to update the\nfirmware. Because it is not available in the default ",{"type":20,"tag":70,"props":88,"children":90},{"className":89},[],[91],{"type":25,"value":92},"yum",{"type":25,"value":94}," repositories, we\nwill enable the ",{"type":20,"tag":96,"props":97,"children":98},"em",{},[99],{"type":25,"value":100},"Extra Packages for Enterprise Linux",{"type":25,"value":102}," (EPEL) repository before\ninstallation.",{"type":20,"tag":65,"props":104,"children":108},{"code":105,"language":106,"meta":7,"className":107,"style":7},"sudo yum install epel-release\nsudo yum install flashrom\n","bash","language-bash shiki shiki-themes github-light",[109],{"type":20,"tag":70,"props":110,"children":111},{"__ignoreMap":7},[112,140],{"type":20,"tag":113,"props":114,"children":117},"span",{"class":115,"line":116},"line",1,[118,124,130,135],{"type":20,"tag":113,"props":119,"children":121},{"style":120},"--shiki-default:#6F42C1",[122],{"type":25,"value":123},"sudo",{"type":20,"tag":113,"props":125,"children":127},{"style":126},"--shiki-default:#032F62",[128],{"type":25,"value":129}," yum",{"type":20,"tag":113,"props":131,"children":132},{"style":126},[133],{"type":25,"value":134}," install",{"type":20,"tag":113,"props":136,"children":137},{"style":126},[138],{"type":25,"value":139}," epel-release\n",{"type":20,"tag":113,"props":141,"children":143},{"class":115,"line":142},2,[144,148,152,156],{"type":20,"tag":113,"props":145,"children":146},{"style":120},[147],{"type":25,"value":123},{"type":20,"tag":113,"props":149,"children":150},{"style":126},[151],{"type":25,"value":129},{"type":20,"tag":113,"props":153,"children":154},{"style":126},[155],{"type":25,"value":134},{"type":20,"tag":113,"props":157,"children":158},{"style":126},[159],{"type":25,"value":160}," flashrom\n",{"type":20,"tag":21,"props":162,"children":163},{},[164,166,172],{"type":25,"value":165},"Next, we will download the latest version of the firmware that is compatible\nwith the APU2 device from the PC Engines release website:\n",{"type":20,"tag":28,"props":167,"children":170},{"href":168,"rel":169},"https://pcengines.github.io/",[32],[171],{"type":25,"value":168},{"type":25,"value":173},".",{"type":20,"tag":65,"props":175,"children":177},{"code":176,"language":106,"meta":7,"className":107,"style":7},"curl -O https://3mdeb.com/open-source-firmware/pcengines/apu2/apu2_v4.11.0.1.rom\n",[178],{"type":20,"tag":70,"props":179,"children":180},{"__ignoreMap":7},[181],{"type":20,"tag":113,"props":182,"children":183},{"class":115,"line":116},[184,189,195],{"type":20,"tag":113,"props":185,"children":186},{"style":120},[187],{"type":25,"value":188},"curl",{"type":20,"tag":113,"props":190,"children":192},{"style":191},"--shiki-default:#005CC5",[193],{"type":25,"value":194}," -O",{"type":20,"tag":113,"props":196,"children":197},{"style":126},[198],{"type":25,"value":199}," https://3mdeb.com/open-source-firmware/pcengines/apu2/apu2_v4.11.0.1.rom\n",{"type":20,"tag":21,"props":201,"children":202},{},[203],{"type":25,"value":204},"And finally, we will flash the firmware...",{"type":20,"tag":65,"props":206,"children":208},{"code":207,"language":106,"meta":7,"className":107,"style":7},"sudo flashrom -w apu2_v4.11.0.1.rom -p internal:boardmismatch=force\n",[209],{"type":20,"tag":70,"props":210,"children":211},{"__ignoreMap":7},[212],{"type":20,"tag":113,"props":213,"children":214},{"class":115,"line":116},[215,219,224,229,234,239],{"type":20,"tag":113,"props":216,"children":217},{"style":120},[218],{"type":25,"value":123},{"type":20,"tag":113,"props":220,"children":221},{"style":126},[222],{"type":25,"value":223}," flashrom",{"type":20,"tag":113,"props":225,"children":226},{"style":191},[227],{"type":25,"value":228}," -w",{"type":20,"tag":113,"props":230,"children":231},{"style":126},[232],{"type":25,"value":233}," apu2_v4.11.0.1.rom",{"type":20,"tag":113,"props":235,"children":236},{"style":191},[237],{"type":25,"value":238}," -p",{"type":20,"tag":113,"props":240,"children":241},{"style":126},[242],{"type":25,"value":243}," internal:boardmismatch=force\n",{"type":20,"tag":21,"props":245,"children":246},{},[247],{"type":20,"tag":248,"props":249,"children":250},"strong",{},[251],{"type":25,"value":252},"References:",{"type":20,"tag":254,"props":255,"children":256},"ul",{},[257,266,274,283,292],{"type":20,"tag":258,"props":259,"children":260},"li",{},[261],{"type":20,"tag":28,"props":262,"children":264},{"href":30,"rel":263},[32],[265],{"type":25,"value":30},{"type":20,"tag":258,"props":267,"children":268},{},[269],{"type":20,"tag":28,"props":270,"children":272},{"href":168,"rel":271},[32],[273],{"type":25,"value":168},{"type":20,"tag":258,"props":275,"children":276},{},[277],{"type":20,"tag":28,"props":278,"children":281},{"href":279,"rel":280},"https://github.com/pcengines/apu2-documentation/blob/master/docs/firmware_flashing.md",[32],[282],{"type":25,"value":279},{"type":20,"tag":258,"props":284,"children":285},{},[286],{"type":20,"tag":28,"props":287,"children":290},{"href":288,"rel":289},"https://github.com/pcengines/apu2-documentation/blob/master/docs/cold_reset.md",[32],[291],{"type":25,"value":288},{"type":20,"tag":258,"props":293,"children":294},{},[295],{"type":20,"tag":28,"props":296,"children":299},{"href":297,"rel":298},"https://github.com/elad/openbsd-apu2",[32],[300],{"type":25,"value":297},{"type":20,"tag":302,"props":303,"children":304},"style",{},[305],{"type":25,"value":306},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":142,"depth":142,"links":308},[],"markdown","content:articles:apu2-firmware-upgrade.md","content","articles/apu2-firmware-upgrade.md","articles/apu2-firmware-upgrade","md",1726174739569] \ No newline at end of file +[{"data":1,"prerenderedAt":314},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"draft":6,"tags":11,"categories":14,"excerpt":16,"body":43,"_type":309,"_id":310,"_source":311,"_file":312,"_extension":313},"/articles/apu2-firmware-upgrade","articles",false,"","Upgrading the Firmware on the PCEngines APU2","I've had a PCEngines APU2 gathering dust for a\nfew years, and have recently decided to dust it off.","2019-12-21",[12,13],"pcengine","apu",[15],"linux",{"type":17,"children":18},"root",[19,38],{"type":20,"tag":21,"props":22,"children":23},"element","p",{},[24,27,36],{"type":25,"value":26},"text","I've had a ",{"type":20,"tag":28,"props":29,"children":33},"a",{"href":30,"rel":31},"https://pcengines.ch/apu2.htm",[32],"nofollow",[34],{"type":25,"value":35},"PCEngines APU2",{"type":25,"value":37}," gathering dust for a\nfew years, and have recently decided to dust it off.",{"type":20,"tag":21,"props":39,"children":40},{},[41],{"type":25,"value":42},"Since the last time the device has been powered on, there have been many great\nimprovements to the firmware, and it was very-much due for an upgrade. The\nfollowing steps outline how the firmware was upgraded on the APU from the\nalready-installed operating system -- CentOS.",{"type":17,"children":44,"toc":307},[45,55,59,64,74,103,161,174,200,205,244,253,301],{"type":20,"tag":21,"props":46,"children":47},{},[48,49,54],{"type":25,"value":26},{"type":20,"tag":28,"props":50,"children":52},{"href":30,"rel":51},[32],[53],{"type":25,"value":35},{"type":25,"value":37},{"type":20,"tag":21,"props":56,"children":57},{},[58],{"type":25,"value":42},{"type":20,"tag":21,"props":60,"children":61},{},[62],{"type":25,"value":63},"First, we will connect to the device over the serial port",{"type":20,"tag":65,"props":66,"children":68},"pre",{"code":67},"screen /dev/tty.usbserial 115200\n",[69],{"type":20,"tag":70,"props":71,"children":72},"code",{"__ignoreMap":7},[73],{"type":25,"value":67},{"type":20,"tag":21,"props":75,"children":76},{},[77,79,85,87,93,95,101],{"type":25,"value":78},"Then, we will install the ",{"type":20,"tag":70,"props":80,"children":82},{"className":81},[],[83],{"type":25,"value":84},"flashrom",{"type":25,"value":86}," utility that is needed to update the\nfirmware. Because it is not available in the default ",{"type":20,"tag":70,"props":88,"children":90},{"className":89},[],[91],{"type":25,"value":92},"yum",{"type":25,"value":94}," repositories, we\nwill enable the ",{"type":20,"tag":96,"props":97,"children":98},"em",{},[99],{"type":25,"value":100},"Extra Packages for Enterprise Linux",{"type":25,"value":102}," (EPEL) repository before\ninstallation.",{"type":20,"tag":65,"props":104,"children":108},{"code":105,"language":106,"meta":7,"className":107,"style":7},"sudo yum install epel-release\nsudo yum install flashrom\n","bash","language-bash shiki shiki-themes github-light",[109],{"type":20,"tag":70,"props":110,"children":111},{"__ignoreMap":7},[112,140],{"type":20,"tag":113,"props":114,"children":117},"span",{"class":115,"line":116},"line",1,[118,124,130,135],{"type":20,"tag":113,"props":119,"children":121},{"style":120},"--shiki-default:#6F42C1",[122],{"type":25,"value":123},"sudo",{"type":20,"tag":113,"props":125,"children":127},{"style":126},"--shiki-default:#032F62",[128],{"type":25,"value":129}," yum",{"type":20,"tag":113,"props":131,"children":132},{"style":126},[133],{"type":25,"value":134}," install",{"type":20,"tag":113,"props":136,"children":137},{"style":126},[138],{"type":25,"value":139}," epel-release\n",{"type":20,"tag":113,"props":141,"children":143},{"class":115,"line":142},2,[144,148,152,156],{"type":20,"tag":113,"props":145,"children":146},{"style":120},[147],{"type":25,"value":123},{"type":20,"tag":113,"props":149,"children":150},{"style":126},[151],{"type":25,"value":129},{"type":20,"tag":113,"props":153,"children":154},{"style":126},[155],{"type":25,"value":134},{"type":20,"tag":113,"props":157,"children":158},{"style":126},[159],{"type":25,"value":160}," flashrom\n",{"type":20,"tag":21,"props":162,"children":163},{},[164,166,172],{"type":25,"value":165},"Next, we will download the latest version of the firmware that is compatible\nwith the APU2 device from the PC Engines release website:\n",{"type":20,"tag":28,"props":167,"children":170},{"href":168,"rel":169},"https://pcengines.github.io/",[32],[171],{"type":25,"value":168},{"type":25,"value":173},".",{"type":20,"tag":65,"props":175,"children":177},{"code":176,"language":106,"meta":7,"className":107,"style":7},"curl -O https://3mdeb.com/open-source-firmware/pcengines/apu2/apu2_v4.11.0.1.rom\n",[178],{"type":20,"tag":70,"props":179,"children":180},{"__ignoreMap":7},[181],{"type":20,"tag":113,"props":182,"children":183},{"class":115,"line":116},[184,189,195],{"type":20,"tag":113,"props":185,"children":186},{"style":120},[187],{"type":25,"value":188},"curl",{"type":20,"tag":113,"props":190,"children":192},{"style":191},"--shiki-default:#005CC5",[193],{"type":25,"value":194}," -O",{"type":20,"tag":113,"props":196,"children":197},{"style":126},[198],{"type":25,"value":199}," https://3mdeb.com/open-source-firmware/pcengines/apu2/apu2_v4.11.0.1.rom\n",{"type":20,"tag":21,"props":201,"children":202},{},[203],{"type":25,"value":204},"And finally, we will flash the firmware...",{"type":20,"tag":65,"props":206,"children":208},{"code":207,"language":106,"meta":7,"className":107,"style":7},"sudo flashrom -w apu2_v4.11.0.1.rom -p internal:boardmismatch=force\n",[209],{"type":20,"tag":70,"props":210,"children":211},{"__ignoreMap":7},[212],{"type":20,"tag":113,"props":213,"children":214},{"class":115,"line":116},[215,219,224,229,234,239],{"type":20,"tag":113,"props":216,"children":217},{"style":120},[218],{"type":25,"value":123},{"type":20,"tag":113,"props":220,"children":221},{"style":126},[222],{"type":25,"value":223}," flashrom",{"type":20,"tag":113,"props":225,"children":226},{"style":191},[227],{"type":25,"value":228}," -w",{"type":20,"tag":113,"props":230,"children":231},{"style":126},[232],{"type":25,"value":233}," apu2_v4.11.0.1.rom",{"type":20,"tag":113,"props":235,"children":236},{"style":191},[237],{"type":25,"value":238}," -p",{"type":20,"tag":113,"props":240,"children":241},{"style":126},[242],{"type":25,"value":243}," internal:boardmismatch=force\n",{"type":20,"tag":21,"props":245,"children":246},{},[247],{"type":20,"tag":248,"props":249,"children":250},"strong",{},[251],{"type":25,"value":252},"References:",{"type":20,"tag":254,"props":255,"children":256},"ul",{},[257,266,274,283,292],{"type":20,"tag":258,"props":259,"children":260},"li",{},[261],{"type":20,"tag":28,"props":262,"children":264},{"href":30,"rel":263},[32],[265],{"type":25,"value":30},{"type":20,"tag":258,"props":267,"children":268},{},[269],{"type":20,"tag":28,"props":270,"children":272},{"href":168,"rel":271},[32],[273],{"type":25,"value":168},{"type":20,"tag":258,"props":275,"children":276},{},[277],{"type":20,"tag":28,"props":278,"children":281},{"href":279,"rel":280},"https://github.com/pcengines/apu2-documentation/blob/master/docs/firmware_flashing.md",[32],[282],{"type":25,"value":279},{"type":20,"tag":258,"props":284,"children":285},{},[286],{"type":20,"tag":28,"props":287,"children":290},{"href":288,"rel":289},"https://github.com/pcengines/apu2-documentation/blob/master/docs/cold_reset.md",[32],[291],{"type":25,"value":288},{"type":20,"tag":258,"props":293,"children":294},{},[295],{"type":20,"tag":28,"props":296,"children":299},{"href":297,"rel":298},"https://github.com/elad/openbsd-apu2",[32],[300],{"type":25,"value":297},{"type":20,"tag":302,"props":303,"children":304},"style",{},[305],{"type":25,"value":306},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":142,"depth":142,"links":308},[],"markdown","content:articles:apu2-firmware-upgrade.md","content","articles/apu2-firmware-upgrade.md","md",1727638398161] \ No newline at end of file diff --git a/articles/apu2-firmware-upgrade/index.html b/articles/apu2-firmware-upgrade/index.html index f2ac22aa..0100ca93 100644 --- a/articles/apu2-firmware-upgrade/index.html +++ b/articles/apu2-firmware-upgrade/index.html @@ -4,36 +4,35 @@ - - + + - - - - + + + + - - + - - - - - - - - - - - - - - - - -
            Category

            Upgrading the Firmware on the PCEngines APU2

            I've had a PCEngines APU2 gathering dust for a + + + + + + + + + + + + + + + + +

            Category

            Upgrading the Firmware on the PCEngines APU2

            I've had a PCEngines APU2 gathering dust for a few years, and have recently decided to dust it off.

            Since the last time the device has been powered on, there have been many great improvements to the firmware, and it was very-much due for an upgrade. The following steps outline how the firmware was upgraded on the APU from the @@ -47,5 +46,5 @@ with the APU2 device from the PC Engines release website: https://pcengines.github.io/.

            curl -O https://3mdeb.com/open-source-firmware/pcengines/apu2/apu2_v4.11.0.1.rom
             

            And finally, we will flash the firmware...

            sudo flashrom -w apu2_v4.11.0.1.rom -p internal:boardmismatch=force
            -

            References:

            - \ No newline at end of file +

            References:

            + \ No newline at end of file diff --git a/articles/docker-selinux-volumes/_payload.json b/articles/docker-selinux-volumes/_payload.json index 1466ee2e..c31ca3b8 100644 --- a/articles/docker-selinux-volumes/_payload.json +++ b/articles/docker-selinux-volumes/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":240},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"draft":6,"tags":11,"categories":14,"excerpt":16,"body":26,"_type":234,"_id":235,"_source":236,"_file":237,"_stem":238,"_extension":239},"/articles/docker-selinux-volumes","articles",false,"","Docker Volume Permissions with SELinux","Unfamiliar with running Docker on a SELinux enabled system, I found myself\nrunning into a bunch of file permission errors while creating volumes.","2019-12-26",[12,13],"docker","selinux",[15],"linux",{"type":17,"children":18},"root",[19],{"type":20,"tag":21,"props":22,"children":23},"element","p",{},[24],{"type":25,"value":9},"text",{"type":17,"children":27,"toc":232},[28,32,53,57,139,160,168,173,190,199,226],{"type":20,"tag":21,"props":29,"children":30},{},[31],{"type":25,"value":9},{"type":20,"tag":33,"props":34,"children":38},"pre",{"code":35,"language":36,"meta":7,"className":37,"style":7},"mkdir: can't create directory '/data': Permission denied\n","txt","language-txt shiki shiki-themes github-light",[39],{"type":20,"tag":40,"props":41,"children":42},"code",{"__ignoreMap":7},[43],{"type":20,"tag":44,"props":45,"children":48},"span",{"class":46,"line":47},"line",1,[49],{"type":20,"tag":44,"props":50,"children":51},{},[52],{"type":25,"value":35},{"type":20,"tag":54,"props":55,"children":56},"hr",{},[],{"type":20,"tag":33,"props":58,"children":62},{"code":59,"language":60,"meta":7,"className":61,"style":7},"$ docker info --format '{{json .SecurityOptions}}'\n[\n \"name=seccomp,profile=/etc/docker/seccomp.json\",\n \"name=selinux\"\n]\n","bash","language-bash shiki shiki-themes github-light",[63],{"type":20,"tag":40,"props":64,"children":65},{"__ignoreMap":7},[66,97,107,121,130],{"type":20,"tag":44,"props":67,"children":68},{"class":46,"line":47},[69,75,81,86,92],{"type":20,"tag":44,"props":70,"children":72},{"style":71},"--shiki-default:#6F42C1",[73],{"type":25,"value":74},"$",{"type":20,"tag":44,"props":76,"children":78},{"style":77},"--shiki-default:#032F62",[79],{"type":25,"value":80}," docker",{"type":20,"tag":44,"props":82,"children":83},{"style":77},[84],{"type":25,"value":85}," info",{"type":20,"tag":44,"props":87,"children":89},{"style":88},"--shiki-default:#005CC5",[90],{"type":25,"value":91}," --format",{"type":20,"tag":44,"props":93,"children":94},{"style":77},[95],{"type":25,"value":96}," '{{json .SecurityOptions}}'\n",{"type":20,"tag":44,"props":98,"children":100},{"class":46,"line":99},2,[101],{"type":20,"tag":44,"props":102,"children":104},{"style":103},"--shiki-default:#24292E",[105],{"type":25,"value":106},"[\n",{"type":20,"tag":44,"props":108,"children":110},{"class":46,"line":109},3,[111,116],{"type":20,"tag":44,"props":112,"children":113},{"style":77},[114],{"type":25,"value":115}," \"name=seccomp,profile=/etc/docker/seccomp.json\"",{"type":20,"tag":44,"props":117,"children":118},{"style":103},[119],{"type":25,"value":120},",\n",{"type":20,"tag":44,"props":122,"children":124},{"class":46,"line":123},4,[125],{"type":20,"tag":44,"props":126,"children":127},{"style":77},[128],{"type":25,"value":129}," \"name=selinux\"\n",{"type":20,"tag":44,"props":131,"children":133},{"class":46,"line":132},5,[134],{"type":20,"tag":44,"props":135,"children":136},{"style":103},[137],{"type":25,"value":138},"]\n",{"type":20,"tag":21,"props":140,"children":141},{},[142,144,150,152,158],{"type":25,"value":143},"It turns out that this can be resolved by appending the ",{"type":20,"tag":40,"props":145,"children":147},{"className":146},[],[148],{"type":25,"value":149},":z",{"type":25,"value":151}," flag to the volume\nmappings in the ",{"type":20,"tag":40,"props":153,"children":155},{"className":154},[],[156],{"type":25,"value":157},"docker-compose.yml",{"type":25,"value":159}," file, indicating that the volume content\nis shared.",{"type":20,"tag":33,"props":161,"children":163},{"code":162},"services:\n server:\n volumes:\n - ./data:/data:z\n",[164],{"type":20,"tag":40,"props":165,"children":166},{"__ignoreMap":7},[167],{"type":25,"value":162},{"type":20,"tag":21,"props":169,"children":170},{},[171],{"type":25,"value":172},"From the Docker documentation:",{"type":20,"tag":174,"props":175,"children":176},"blockquote",{},[177],{"type":20,"tag":21,"props":178,"children":179},{},[180,182,188],{"type":25,"value":181},"The ",{"type":20,"tag":40,"props":183,"children":185},{"className":184},[],[186],{"type":25,"value":187},"z",{"type":25,"value":189}," option tells Docker that two containers share the volume content. As\na result, Docker labels the content with a shared content label. Shared\nvolume labels allow all containers to read/write content.",{"type":20,"tag":21,"props":191,"children":192},{},[193],{"type":20,"tag":194,"props":195,"children":196},"strong",{},[197],{"type":25,"value":198},"References",{"type":20,"tag":200,"props":201,"children":202},"ul",{},[203,216],{"type":20,"tag":204,"props":205,"children":206},"li",{},[207],{"type":20,"tag":208,"props":209,"children":213},"a",{"href":210,"rel":211},"https://docs.docker.com/engine/reference/commandline/info/",[212],"nofollow",[214],{"type":25,"value":215},"Docker Docs: Docker Info",{"type":20,"tag":204,"props":217,"children":218},{},[219],{"type":20,"tag":208,"props":220,"children":223},{"href":221,"rel":222},"https://docs.docker.com/engine/reference/commandline/run/#mount-volumes-from-container---volumes-from",[212],[224],{"type":25,"value":225},"Docker Docs: Mounting Volumes",{"type":20,"tag":227,"props":228,"children":229},"style",{},[230],{"type":25,"value":231},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":99,"depth":99,"links":233},[],"markdown","content:articles:docker-selinux-volumes.md","content","articles/docker-selinux-volumes.md","articles/docker-selinux-volumes","md",1726174739557] \ No newline at end of file +[{"data":1,"prerenderedAt":239},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"draft":6,"tags":11,"categories":14,"excerpt":16,"body":26,"_type":234,"_id":235,"_source":236,"_file":237,"_extension":238},"/articles/docker-selinux-volumes","articles",false,"","Docker Volume Permissions with SELinux","Unfamiliar with running Docker on a SELinux enabled system, I found myself\nrunning into a bunch of file permission errors while creating volumes.","2019-12-26",[12,13],"docker","selinux",[15],"linux",{"type":17,"children":18},"root",[19],{"type":20,"tag":21,"props":22,"children":23},"element","p",{},[24],{"type":25,"value":9},"text",{"type":17,"children":27,"toc":232},[28,32,53,57,139,160,168,173,190,199,226],{"type":20,"tag":21,"props":29,"children":30},{},[31],{"type":25,"value":9},{"type":20,"tag":33,"props":34,"children":38},"pre",{"code":35,"language":36,"meta":7,"className":37,"style":7},"mkdir: can't create directory '/data': Permission denied\n","txt","language-txt shiki shiki-themes github-light",[39],{"type":20,"tag":40,"props":41,"children":42},"code",{"__ignoreMap":7},[43],{"type":20,"tag":44,"props":45,"children":48},"span",{"class":46,"line":47},"line",1,[49],{"type":20,"tag":44,"props":50,"children":51},{},[52],{"type":25,"value":35},{"type":20,"tag":54,"props":55,"children":56},"hr",{},[],{"type":20,"tag":33,"props":58,"children":62},{"code":59,"language":60,"meta":7,"className":61,"style":7},"$ docker info --format '{{json .SecurityOptions}}'\n[\n \"name=seccomp,profile=/etc/docker/seccomp.json\",\n \"name=selinux\"\n]\n","bash","language-bash shiki shiki-themes github-light",[63],{"type":20,"tag":40,"props":64,"children":65},{"__ignoreMap":7},[66,97,107,121,130],{"type":20,"tag":44,"props":67,"children":68},{"class":46,"line":47},[69,75,81,86,92],{"type":20,"tag":44,"props":70,"children":72},{"style":71},"--shiki-default:#6F42C1",[73],{"type":25,"value":74},"$",{"type":20,"tag":44,"props":76,"children":78},{"style":77},"--shiki-default:#032F62",[79],{"type":25,"value":80}," docker",{"type":20,"tag":44,"props":82,"children":83},{"style":77},[84],{"type":25,"value":85}," info",{"type":20,"tag":44,"props":87,"children":89},{"style":88},"--shiki-default:#005CC5",[90],{"type":25,"value":91}," --format",{"type":20,"tag":44,"props":93,"children":94},{"style":77},[95],{"type":25,"value":96}," '{{json .SecurityOptions}}'\n",{"type":20,"tag":44,"props":98,"children":100},{"class":46,"line":99},2,[101],{"type":20,"tag":44,"props":102,"children":104},{"style":103},"--shiki-default:#24292E",[105],{"type":25,"value":106},"[\n",{"type":20,"tag":44,"props":108,"children":110},{"class":46,"line":109},3,[111,116],{"type":20,"tag":44,"props":112,"children":113},{"style":77},[114],{"type":25,"value":115}," \"name=seccomp,profile=/etc/docker/seccomp.json\"",{"type":20,"tag":44,"props":117,"children":118},{"style":103},[119],{"type":25,"value":120},",\n",{"type":20,"tag":44,"props":122,"children":124},{"class":46,"line":123},4,[125],{"type":20,"tag":44,"props":126,"children":127},{"style":77},[128],{"type":25,"value":129}," \"name=selinux\"\n",{"type":20,"tag":44,"props":131,"children":133},{"class":46,"line":132},5,[134],{"type":20,"tag":44,"props":135,"children":136},{"style":103},[137],{"type":25,"value":138},"]\n",{"type":20,"tag":21,"props":140,"children":141},{},[142,144,150,152,158],{"type":25,"value":143},"It turns out that this can be resolved by appending the ",{"type":20,"tag":40,"props":145,"children":147},{"className":146},[],[148],{"type":25,"value":149},":z",{"type":25,"value":151}," flag to the volume\nmappings in the ",{"type":20,"tag":40,"props":153,"children":155},{"className":154},[],[156],{"type":25,"value":157},"docker-compose.yml",{"type":25,"value":159}," file, indicating that the volume content\nis shared.",{"type":20,"tag":33,"props":161,"children":163},{"code":162},"services:\n server:\n volumes:\n - ./data:/data:z\n",[164],{"type":20,"tag":40,"props":165,"children":166},{"__ignoreMap":7},[167],{"type":25,"value":162},{"type":20,"tag":21,"props":169,"children":170},{},[171],{"type":25,"value":172},"From the Docker documentation:",{"type":20,"tag":174,"props":175,"children":176},"blockquote",{},[177],{"type":20,"tag":21,"props":178,"children":179},{},[180,182,188],{"type":25,"value":181},"The ",{"type":20,"tag":40,"props":183,"children":185},{"className":184},[],[186],{"type":25,"value":187},"z",{"type":25,"value":189}," option tells Docker that two containers share the volume content. As\na result, Docker labels the content with a shared content label. Shared\nvolume labels allow all containers to read/write content.",{"type":20,"tag":21,"props":191,"children":192},{},[193],{"type":20,"tag":194,"props":195,"children":196},"strong",{},[197],{"type":25,"value":198},"References",{"type":20,"tag":200,"props":201,"children":202},"ul",{},[203,216],{"type":20,"tag":204,"props":205,"children":206},"li",{},[207],{"type":20,"tag":208,"props":209,"children":213},"a",{"href":210,"rel":211},"https://docs.docker.com/engine/reference/commandline/info/",[212],"nofollow",[214],{"type":25,"value":215},"Docker Docs: Docker Info",{"type":20,"tag":204,"props":217,"children":218},{},[219],{"type":20,"tag":208,"props":220,"children":223},{"href":221,"rel":222},"https://docs.docker.com/engine/reference/commandline/run/#mount-volumes-from-container---volumes-from",[212],[224],{"type":25,"value":225},"Docker Docs: Mounting Volumes",{"type":20,"tag":227,"props":228,"children":229},"style",{},[230],{"type":25,"value":231},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":99,"depth":99,"links":233},[],"markdown","content:articles:docker-selinux-volumes.md","content","articles/docker-selinux-volumes.md","md",1727638398126] \ No newline at end of file diff --git a/articles/docker-selinux-volumes/index.html b/articles/docker-selinux-volumes/index.html index b1a84f3a..04f59c91 100644 --- a/articles/docker-selinux-volumes/index.html +++ b/articles/docker-selinux-volumes/index.html @@ -4,37 +4,36 @@ - - + + - - - - + + + + - - + - - - - - - - - - - - - - - - - - -
            Category

            Docker Volume Permissions with SELinux

            Unfamiliar with running Docker on a SELinux enabled system, I found myself + + + + + + + + + + + + + + + + + +

            Category

            Docker Volume Permissions with SELinux

            Unfamiliar with running Docker on a SELinux enabled system, I found myself running into a bunch of file permission errors while creating volumes.

            mkdir: can't create directory '/data': Permission denied
             

            $ docker info --format '{{json .SecurityOptions}}'
             [
            @@ -49,5 +48,5 @@
                   - ./data:/data:z
             

            From the Docker documentation:

            The z option tells Docker that two containers share the volume content. As a result, Docker labels the content with a shared content label. Shared -volume labels allow all containers to read/write content.

            References

            - \ No newline at end of file +volume labels allow all containers to read/write content.

            References

            + \ No newline at end of file diff --git a/articles/doctl/_payload.json b/articles/doctl/_payload.json index e3b26263..3ca09a0b 100644 --- a/articles/doctl/_payload.json +++ b/articles/doctl/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":712},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"tags":11,"categories":14,"excerpt":15,"body":43,"_type":706,"_id":707,"_source":708,"_file":709,"_stem":710,"_extension":711},"/articles/doctl","articles",false,"","Exploring the Digital Ocean `doctl` Utility","I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean doctl command line utility.\nThis proved to be an extremely easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future.","2023-01-01",[12,13],"linux","digital-ocean",[12],{"type":16,"children":17},"root",[18],{"type":19,"tag":20,"props":21,"children":22},"element","p",{},[23,26,33,35,41],{"type":24,"value":25},"text","I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean ",{"type":19,"tag":27,"props":28,"children":30},"code",{"className":29},[],[31],{"type":24,"value":32},"doctl",{"type":24,"value":34}," command line utility.\nThis proved to be an ",{"type":19,"tag":36,"props":37,"children":38},"em",{},[39],{"type":24,"value":40},"extremely",{"type":24,"value":42}," easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future.",{"type":16,"children":44,"toc":704},[45,60,76,156,177,212,217,289,294,389,402,452,465,495,500,624,629,657,693,698],{"type":19,"tag":20,"props":46,"children":47},{},[48,49,54,55,59],{"type":24,"value":25},{"type":19,"tag":27,"props":50,"children":52},{"className":51},[],[53],{"type":24,"value":32},{"type":24,"value":34},{"type":19,"tag":36,"props":56,"children":57},{},[58],{"type":24,"value":40},{"type":24,"value":42},{"type":19,"tag":20,"props":61,"children":62},{},[63,65,74],{"type":24,"value":64},"To start things off, I had to install and setup authentication to Digital Ocean. Doing\nthis on my Mac machine, I opted to use ",{"type":19,"tag":66,"props":67,"children":71},"a",{"href":68,"rel":69},"https://brew.sh/",[70],"nofollow",[72],{"type":24,"value":73},"Homebrew",{"type":24,"value":75},".",{"type":19,"tag":77,"props":78,"children":82},"pre",{"className":79,"code":80,"language":81,"meta":7,"style":7},"language-sh shiki shiki-themes github-light","# install `doctl`\nbrew install doctl\n\n# setup authentication\ndoctl auth init\n","sh",[83],{"type":19,"tag":27,"props":84,"children":85},{"__ignoreMap":7},[86,98,119,129,138],{"type":19,"tag":87,"props":88,"children":91},"span",{"class":89,"line":90},"line",1,[92],{"type":19,"tag":87,"props":93,"children":95},{"style":94},"--shiki-default:#6A737D",[96],{"type":24,"value":97},"# install `doctl`\n",{"type":19,"tag":87,"props":99,"children":101},{"class":89,"line":100},2,[102,108,114],{"type":19,"tag":87,"props":103,"children":105},{"style":104},"--shiki-default:#6F42C1",[106],{"type":24,"value":107},"brew",{"type":19,"tag":87,"props":109,"children":111},{"style":110},"--shiki-default:#032F62",[112],{"type":24,"value":113}," install",{"type":19,"tag":87,"props":115,"children":116},{"style":110},[117],{"type":24,"value":118}," doctl\n",{"type":19,"tag":87,"props":120,"children":122},{"class":89,"line":121},3,[123],{"type":19,"tag":87,"props":124,"children":126},{"emptyLinePlaceholder":125},true,[127],{"type":24,"value":128},"\n",{"type":19,"tag":87,"props":130,"children":132},{"class":89,"line":131},4,[133],{"type":19,"tag":87,"props":134,"children":135},{"style":94},[136],{"type":24,"value":137},"# setup authentication\n",{"type":19,"tag":87,"props":139,"children":141},{"class":89,"line":140},5,[142,146,151],{"type":19,"tag":87,"props":143,"children":144},{"style":104},[145],{"type":24,"value":32},{"type":19,"tag":87,"props":147,"children":148},{"style":110},[149],{"type":24,"value":150}," auth",{"type":19,"tag":87,"props":152,"children":153},{"style":110},[154],{"type":24,"value":155}," init\n",{"type":19,"tag":20,"props":157,"children":158},{},[159,161,168,170,176],{"type":24,"value":160},"While the online ",{"type":19,"tag":66,"props":162,"children":165},{"href":163,"rel":164},"https://docs.digitalocean.com/reference/doctl/reference/compute/droplet/create/",[70],[166],{"type":24,"value":167},"documentation",{"type":24,"value":169}," is fantastic, I instead found myself mostly referencing the outputs of ",{"type":19,"tag":27,"props":171,"children":173},{"className":172},[],[174],{"type":24,"value":175},"--help",{"type":24,"value":75},{"type":19,"tag":77,"props":178,"children":180},{"className":79,"code":179,"language":81,"meta":7,"style":7},"doctl compute droplet create --help\n",[181],{"type":19,"tag":27,"props":182,"children":183},{"__ignoreMap":7},[184],{"type":19,"tag":87,"props":185,"children":186},{"class":89,"line":90},[187,191,196,201,206],{"type":19,"tag":87,"props":188,"children":189},{"style":104},[190],{"type":24,"value":32},{"type":19,"tag":87,"props":192,"children":193},{"style":110},[194],{"type":24,"value":195}," compute",{"type":19,"tag":87,"props":197,"children":198},{"style":110},[199],{"type":24,"value":200}," droplet",{"type":19,"tag":87,"props":202,"children":203},{"style":110},[204],{"type":24,"value":205}," create",{"type":19,"tag":87,"props":207,"children":209},{"style":208},"--shiki-default:#005CC5",[210],{"type":24,"value":211}," --help\n",{"type":19,"tag":20,"props":213,"children":214},{},[215],{"type":24,"value":216},"I had to find the image name of the version of Ubuntu I wanted to install:",{"type":19,"tag":77,"props":218,"children":220},{"className":79,"code":219,"language":81,"meta":7,"style":7},"doctl compute image list --public | grep ubuntu-22\n\n# 118857366 22.04 (LTS) x64 snapshot Ubuntu ubuntu-22-04-x64 true 7\n# 119383150 22.10 x64 snapshot Ubuntu ubuntu-22-10-x64 true 7\n",[221],{"type":19,"tag":27,"props":222,"children":223},{"__ignoreMap":7},[224,266,273,281],{"type":19,"tag":87,"props":225,"children":226},{"class":89,"line":90},[227,231,235,240,245,250,256,261],{"type":19,"tag":87,"props":228,"children":229},{"style":104},[230],{"type":24,"value":32},{"type":19,"tag":87,"props":232,"children":233},{"style":110},[234],{"type":24,"value":195},{"type":19,"tag":87,"props":236,"children":237},{"style":110},[238],{"type":24,"value":239}," image",{"type":19,"tag":87,"props":241,"children":242},{"style":110},[243],{"type":24,"value":244}," list",{"type":19,"tag":87,"props":246,"children":247},{"style":208},[248],{"type":24,"value":249}," --public",{"type":19,"tag":87,"props":251,"children":253},{"style":252},"--shiki-default:#D73A49",[254],{"type":24,"value":255}," |",{"type":19,"tag":87,"props":257,"children":258},{"style":104},[259],{"type":24,"value":260}," grep",{"type":19,"tag":87,"props":262,"children":263},{"style":110},[264],{"type":24,"value":265}," ubuntu-22\n",{"type":19,"tag":87,"props":267,"children":268},{"class":89,"line":100},[269],{"type":19,"tag":87,"props":270,"children":271},{"emptyLinePlaceholder":125},[272],{"type":24,"value":128},{"type":19,"tag":87,"props":274,"children":275},{"class":89,"line":121},[276],{"type":19,"tag":87,"props":277,"children":278},{"style":94},[279],{"type":24,"value":280},"# 118857366 22.04 (LTS) x64 snapshot Ubuntu ubuntu-22-04-x64 true 7\n",{"type":19,"tag":87,"props":282,"children":283},{"class":89,"line":131},[284],{"type":19,"tag":87,"props":285,"children":286},{"style":94},[287],{"type":24,"value":288},"# 119383150 22.10 x64 snapshot Ubuntu ubuntu-22-10-x64 true 7\n",{"type":19,"tag":20,"props":290,"children":291},{},[292],{"type":24,"value":293},"And also the slug of the compute size:",{"type":19,"tag":77,"props":295,"children":297},{"className":79,"code":296,"language":81,"meta":7,"style":7},"doctl compute size list\n\n# Slug Description Memory VCPUs Disk Price Monthly Price Hourly\n# s-1vcpu-512mb-10gb Basic 512 1 10 4.00 0.005950\n# s-1vcpu-1gb Basic 1024 1 25 6.00 0.008930\n# s-1vcpu-1gb-amd Basic AMD 1024 1 25 7.00 0.010420\n# s-1vcpu-1gb-intel Basic Intel 1024 1 25 7.00 0.010420\n# s-1vcpu-2gb Basic 2048 1 50 12.00 0.017860\n# s-1vcpu-2gb-amd Basic AMD 2048 1 50 14.00 0.020830\n",[298],{"type":19,"tag":27,"props":299,"children":300},{"__ignoreMap":7},[301,322,329,337,345,353,362,371,380],{"type":19,"tag":87,"props":302,"children":303},{"class":89,"line":90},[304,308,312,317],{"type":19,"tag":87,"props":305,"children":306},{"style":104},[307],{"type":24,"value":32},{"type":19,"tag":87,"props":309,"children":310},{"style":110},[311],{"type":24,"value":195},{"type":19,"tag":87,"props":313,"children":314},{"style":110},[315],{"type":24,"value":316}," size",{"type":19,"tag":87,"props":318,"children":319},{"style":110},[320],{"type":24,"value":321}," list\n",{"type":19,"tag":87,"props":323,"children":324},{"class":89,"line":100},[325],{"type":19,"tag":87,"props":326,"children":327},{"emptyLinePlaceholder":125},[328],{"type":24,"value":128},{"type":19,"tag":87,"props":330,"children":331},{"class":89,"line":121},[332],{"type":19,"tag":87,"props":333,"children":334},{"style":94},[335],{"type":24,"value":336},"# Slug Description Memory VCPUs Disk Price Monthly Price Hourly\n",{"type":19,"tag":87,"props":338,"children":339},{"class":89,"line":131},[340],{"type":19,"tag":87,"props":341,"children":342},{"style":94},[343],{"type":24,"value":344},"# s-1vcpu-512mb-10gb Basic 512 1 10 4.00 0.005950\n",{"type":19,"tag":87,"props":346,"children":347},{"class":89,"line":140},[348],{"type":19,"tag":87,"props":349,"children":350},{"style":94},[351],{"type":24,"value":352},"# s-1vcpu-1gb Basic 1024 1 25 6.00 0.008930\n",{"type":19,"tag":87,"props":354,"children":356},{"class":89,"line":355},6,[357],{"type":19,"tag":87,"props":358,"children":359},{"style":94},[360],{"type":24,"value":361},"# s-1vcpu-1gb-amd Basic AMD 1024 1 25 7.00 0.010420\n",{"type":19,"tag":87,"props":363,"children":365},{"class":89,"line":364},7,[366],{"type":19,"tag":87,"props":367,"children":368},{"style":94},[369],{"type":24,"value":370},"# s-1vcpu-1gb-intel Basic Intel 1024 1 25 7.00 0.010420\n",{"type":19,"tag":87,"props":372,"children":374},{"class":89,"line":373},8,[375],{"type":19,"tag":87,"props":376,"children":377},{"style":94},[378],{"type":24,"value":379},"# s-1vcpu-2gb Basic 2048 1 50 12.00 0.017860\n",{"type":19,"tag":87,"props":381,"children":383},{"class":89,"line":382},9,[384],{"type":19,"tag":87,"props":385,"children":386},{"style":94},[387],{"type":24,"value":388},"# s-1vcpu-2gb-amd Basic AMD 2048 1 50 14.00 0.020830\n",{"type":19,"tag":20,"props":390,"children":391},{},[392,394,400],{"type":24,"value":393},"I've also configured a few SSH keys with Digital Ocean, and I can have the key (specified by ID) provisioned to the machine using the ",{"type":19,"tag":27,"props":395,"children":397},{"className":396},[],[398],{"type":24,"value":399},"--ssh-keys",{"type":24,"value":401}," flag.",{"type":19,"tag":77,"props":403,"children":405},{"className":79,"code":404,"language":81,"meta":7,"style":7},"doctl compute ssh-key list\n\n# ID Name FingerPrint\n# 1234 mini \u003Credacted>\n",[406],{"type":19,"tag":27,"props":407,"children":408},{"__ignoreMap":7},[409,429,436,444],{"type":19,"tag":87,"props":410,"children":411},{"class":89,"line":90},[412,416,420,425],{"type":19,"tag":87,"props":413,"children":414},{"style":104},[415],{"type":24,"value":32},{"type":19,"tag":87,"props":417,"children":418},{"style":110},[419],{"type":24,"value":195},{"type":19,"tag":87,"props":421,"children":422},{"style":110},[423],{"type":24,"value":424}," ssh-key",{"type":19,"tag":87,"props":426,"children":427},{"style":110},[428],{"type":24,"value":321},{"type":19,"tag":87,"props":430,"children":431},{"class":89,"line":100},[432],{"type":19,"tag":87,"props":433,"children":434},{"emptyLinePlaceholder":125},[435],{"type":24,"value":128},{"type":19,"tag":87,"props":437,"children":438},{"class":89,"line":121},[439],{"type":19,"tag":87,"props":440,"children":441},{"style":94},[442],{"type":24,"value":443},"# ID Name FingerPrint\n",{"type":19,"tag":87,"props":445,"children":446},{"class":89,"line":131},[447],{"type":19,"tag":87,"props":448,"children":449},{"style":94},[450],{"type":24,"value":451},"# 1234 mini \u003Credacted>\n",{"type":19,"tag":20,"props":453,"children":454},{},[455,457,463],{"type":24,"value":456},"Also, I wanted to install a few packages to the box upon creation, this can be done easily with the ",{"type":19,"tag":27,"props":458,"children":460},{"className":459},[],[461],{"type":24,"value":462},"--user-data-file",{"type":24,"value":464}," flag to run an initialization script.",{"type":19,"tag":77,"props":466,"children":468},{"className":79,"code":467,"language":81,"meta":7,"style":7},"echo 'apt install -y imagemagick zip' > bootstrap.sh\n",[469],{"type":19,"tag":27,"props":470,"children":471},{"__ignoreMap":7},[472],{"type":19,"tag":87,"props":473,"children":474},{"class":89,"line":90},[475,480,485,490],{"type":19,"tag":87,"props":476,"children":477},{"style":208},[478],{"type":24,"value":479},"echo",{"type":19,"tag":87,"props":481,"children":482},{"style":110},[483],{"type":24,"value":484}," 'apt install -y imagemagick zip'",{"type":19,"tag":87,"props":486,"children":487},{"style":252},[488],{"type":24,"value":489}," >",{"type":19,"tag":87,"props":491,"children":492},{"style":110},[493],{"type":24,"value":494}," bootstrap.sh\n",{"type":19,"tag":20,"props":496,"children":497},{},[498],{"type":24,"value":499},"Putting it all together, here is the simple command for creating a small compute instance!",{"type":19,"tag":77,"props":501,"children":503},{"className":79,"code":502,"language":81,"meta":7,"style":7},"doctl compute droplet create \\\n --image ubuntu-22-10-x64 \\\n --size s-1vcpu-512mb-10gb \\\n --region nyc1 \\\n --ssh-keys 1234 \\\n --user-data-file boostrap.sh \\\n ephemeral\n",[504],{"type":19,"tag":27,"props":505,"children":506},{"__ignoreMap":7},[507,531,548,565,582,599,616],{"type":19,"tag":87,"props":508,"children":509},{"class":89,"line":90},[510,514,518,522,526],{"type":19,"tag":87,"props":511,"children":512},{"style":104},[513],{"type":24,"value":32},{"type":19,"tag":87,"props":515,"children":516},{"style":110},[517],{"type":24,"value":195},{"type":19,"tag":87,"props":519,"children":520},{"style":110},[521],{"type":24,"value":200},{"type":19,"tag":87,"props":523,"children":524},{"style":110},[525],{"type":24,"value":205},{"type":19,"tag":87,"props":527,"children":528},{"style":208},[529],{"type":24,"value":530}," \\\n",{"type":19,"tag":87,"props":532,"children":533},{"class":89,"line":100},[534,539,544],{"type":19,"tag":87,"props":535,"children":536},{"style":208},[537],{"type":24,"value":538}," --image",{"type":19,"tag":87,"props":540,"children":541},{"style":110},[542],{"type":24,"value":543}," ubuntu-22-10-x64",{"type":19,"tag":87,"props":545,"children":546},{"style":208},[547],{"type":24,"value":530},{"type":19,"tag":87,"props":549,"children":550},{"class":89,"line":121},[551,556,561],{"type":19,"tag":87,"props":552,"children":553},{"style":208},[554],{"type":24,"value":555}," --size",{"type":19,"tag":87,"props":557,"children":558},{"style":110},[559],{"type":24,"value":560}," s-1vcpu-512mb-10gb",{"type":19,"tag":87,"props":562,"children":563},{"style":208},[564],{"type":24,"value":530},{"type":19,"tag":87,"props":566,"children":567},{"class":89,"line":131},[568,573,578],{"type":19,"tag":87,"props":569,"children":570},{"style":208},[571],{"type":24,"value":572}," --region",{"type":19,"tag":87,"props":574,"children":575},{"style":110},[576],{"type":24,"value":577}," nyc1",{"type":19,"tag":87,"props":579,"children":580},{"style":208},[581],{"type":24,"value":530},{"type":19,"tag":87,"props":583,"children":584},{"class":89,"line":140},[585,590,595],{"type":19,"tag":87,"props":586,"children":587},{"style":208},[588],{"type":24,"value":589}," --ssh-keys",{"type":19,"tag":87,"props":591,"children":592},{"style":208},[593],{"type":24,"value":594}," 1234",{"type":19,"tag":87,"props":596,"children":597},{"style":208},[598],{"type":24,"value":530},{"type":19,"tag":87,"props":600,"children":601},{"class":89,"line":355},[602,607,612],{"type":19,"tag":87,"props":603,"children":604},{"style":208},[605],{"type":24,"value":606}," --user-data-file",{"type":19,"tag":87,"props":608,"children":609},{"style":110},[610],{"type":24,"value":611}," boostrap.sh",{"type":19,"tag":87,"props":613,"children":614},{"style":208},[615],{"type":24,"value":530},{"type":19,"tag":87,"props":617,"children":618},{"class":89,"line":364},[619],{"type":19,"tag":87,"props":620,"children":621},{"style":110},[622],{"type":24,"value":623}," ephemeral\n",{"type":19,"tag":20,"props":625,"children":626},{},[627],{"type":24,"value":628},"Finally, I can connect, do my thing, and destroy the instance.",{"type":19,"tag":77,"props":630,"children":632},{"className":79,"code":631,"language":81,"meta":7,"style":7},"doctl compute ssh ephemeral\n",[633],{"type":19,"tag":27,"props":634,"children":635},{"__ignoreMap":7},[636],{"type":19,"tag":87,"props":637,"children":638},{"class":89,"line":90},[639,643,647,652],{"type":19,"tag":87,"props":640,"children":641},{"style":104},[642],{"type":24,"value":32},{"type":19,"tag":87,"props":644,"children":645},{"style":110},[646],{"type":24,"value":195},{"type":19,"tag":87,"props":648,"children":649},{"style":110},[650],{"type":24,"value":651}," ssh",{"type":19,"tag":87,"props":653,"children":654},{"style":110},[655],{"type":24,"value":656}," ephemeral\n",{"type":19,"tag":77,"props":658,"children":660},{"className":79,"code":659,"language":81,"meta":7,"style":7},"doctl compute droplet delete --force ephemeral\n",[661],{"type":19,"tag":27,"props":662,"children":663},{"__ignoreMap":7},[664],{"type":19,"tag":87,"props":665,"children":666},{"class":89,"line":90},[667,671,675,679,684,689],{"type":19,"tag":87,"props":668,"children":669},{"style":104},[670],{"type":24,"value":32},{"type":19,"tag":87,"props":672,"children":673},{"style":110},[674],{"type":24,"value":195},{"type":19,"tag":87,"props":676,"children":677},{"style":110},[678],{"type":24,"value":200},{"type":19,"tag":87,"props":680,"children":681},{"style":110},[682],{"type":24,"value":683}," delete",{"type":19,"tag":87,"props":685,"children":686},{"style":208},[687],{"type":24,"value":688}," --force",{"type":19,"tag":87,"props":690,"children":691},{"style":110},[692],{"type":24,"value":656},{"type":19,"tag":20,"props":694,"children":695},{},[696],{"type":24,"value":697},"All-in-all, I was up and running in about 20 minutes. What a handy utility!",{"type":19,"tag":699,"props":700,"children":701},"style",{},[702],{"type":24,"value":703},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":100,"depth":100,"links":705},[],"markdown","content:articles:doctl.md","content","articles/doctl.md","articles/doctl","md",1726174739511] \ No newline at end of file +[{"data":1,"prerenderedAt":711},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"tags":11,"categories":14,"excerpt":15,"body":43,"_type":706,"_id":707,"_source":708,"_file":709,"_extension":710},"/articles/doctl","articles",false,"","Exploring the Digital Ocean `doctl` Utility","I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean doctl command line utility.\nThis proved to be an extremely easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future.","2023-01-01",[12,13],"linux","digital-ocean",[12],{"type":16,"children":17},"root",[18],{"type":19,"tag":20,"props":21,"children":22},"element","p",{},[23,26,33,35,41],{"type":24,"value":25},"text","I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean ",{"type":19,"tag":27,"props":28,"children":30},"code",{"className":29},[],[31],{"type":24,"value":32},"doctl",{"type":24,"value":34}," command line utility.\nThis proved to be an ",{"type":19,"tag":36,"props":37,"children":38},"em",{},[39],{"type":24,"value":40},"extremely",{"type":24,"value":42}," easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future.",{"type":16,"children":44,"toc":704},[45,60,76,156,177,212,217,289,294,389,402,452,465,495,500,624,629,657,693,698],{"type":19,"tag":20,"props":46,"children":47},{},[48,49,54,55,59],{"type":24,"value":25},{"type":19,"tag":27,"props":50,"children":52},{"className":51},[],[53],{"type":24,"value":32},{"type":24,"value":34},{"type":19,"tag":36,"props":56,"children":57},{},[58],{"type":24,"value":40},{"type":24,"value":42},{"type":19,"tag":20,"props":61,"children":62},{},[63,65,74],{"type":24,"value":64},"To start things off, I had to install and setup authentication to Digital Ocean. Doing\nthis on my Mac machine, I opted to use ",{"type":19,"tag":66,"props":67,"children":71},"a",{"href":68,"rel":69},"https://brew.sh/",[70],"nofollow",[72],{"type":24,"value":73},"Homebrew",{"type":24,"value":75},".",{"type":19,"tag":77,"props":78,"children":82},"pre",{"className":79,"code":80,"language":81,"meta":7,"style":7},"language-sh shiki shiki-themes github-light","# install `doctl`\nbrew install doctl\n\n# setup authentication\ndoctl auth init\n","sh",[83],{"type":19,"tag":27,"props":84,"children":85},{"__ignoreMap":7},[86,98,119,129,138],{"type":19,"tag":87,"props":88,"children":91},"span",{"class":89,"line":90},"line",1,[92],{"type":19,"tag":87,"props":93,"children":95},{"style":94},"--shiki-default:#6A737D",[96],{"type":24,"value":97},"# install `doctl`\n",{"type":19,"tag":87,"props":99,"children":101},{"class":89,"line":100},2,[102,108,114],{"type":19,"tag":87,"props":103,"children":105},{"style":104},"--shiki-default:#6F42C1",[106],{"type":24,"value":107},"brew",{"type":19,"tag":87,"props":109,"children":111},{"style":110},"--shiki-default:#032F62",[112],{"type":24,"value":113}," install",{"type":19,"tag":87,"props":115,"children":116},{"style":110},[117],{"type":24,"value":118}," doctl\n",{"type":19,"tag":87,"props":120,"children":122},{"class":89,"line":121},3,[123],{"type":19,"tag":87,"props":124,"children":126},{"emptyLinePlaceholder":125},true,[127],{"type":24,"value":128},"\n",{"type":19,"tag":87,"props":130,"children":132},{"class":89,"line":131},4,[133],{"type":19,"tag":87,"props":134,"children":135},{"style":94},[136],{"type":24,"value":137},"# setup authentication\n",{"type":19,"tag":87,"props":139,"children":141},{"class":89,"line":140},5,[142,146,151],{"type":19,"tag":87,"props":143,"children":144},{"style":104},[145],{"type":24,"value":32},{"type":19,"tag":87,"props":147,"children":148},{"style":110},[149],{"type":24,"value":150}," auth",{"type":19,"tag":87,"props":152,"children":153},{"style":110},[154],{"type":24,"value":155}," init\n",{"type":19,"tag":20,"props":157,"children":158},{},[159,161,168,170,176],{"type":24,"value":160},"While the online ",{"type":19,"tag":66,"props":162,"children":165},{"href":163,"rel":164},"https://docs.digitalocean.com/reference/doctl/reference/compute/droplet/create/",[70],[166],{"type":24,"value":167},"documentation",{"type":24,"value":169}," is fantastic, I instead found myself mostly referencing the outputs of ",{"type":19,"tag":27,"props":171,"children":173},{"className":172},[],[174],{"type":24,"value":175},"--help",{"type":24,"value":75},{"type":19,"tag":77,"props":178,"children":180},{"className":79,"code":179,"language":81,"meta":7,"style":7},"doctl compute droplet create --help\n",[181],{"type":19,"tag":27,"props":182,"children":183},{"__ignoreMap":7},[184],{"type":19,"tag":87,"props":185,"children":186},{"class":89,"line":90},[187,191,196,201,206],{"type":19,"tag":87,"props":188,"children":189},{"style":104},[190],{"type":24,"value":32},{"type":19,"tag":87,"props":192,"children":193},{"style":110},[194],{"type":24,"value":195}," compute",{"type":19,"tag":87,"props":197,"children":198},{"style":110},[199],{"type":24,"value":200}," droplet",{"type":19,"tag":87,"props":202,"children":203},{"style":110},[204],{"type":24,"value":205}," create",{"type":19,"tag":87,"props":207,"children":209},{"style":208},"--shiki-default:#005CC5",[210],{"type":24,"value":211}," --help\n",{"type":19,"tag":20,"props":213,"children":214},{},[215],{"type":24,"value":216},"I had to find the image name of the version of Ubuntu I wanted to install:",{"type":19,"tag":77,"props":218,"children":220},{"className":79,"code":219,"language":81,"meta":7,"style":7},"doctl compute image list --public | grep ubuntu-22\n\n# 118857366 22.04 (LTS) x64 snapshot Ubuntu ubuntu-22-04-x64 true 7\n# 119383150 22.10 x64 snapshot Ubuntu ubuntu-22-10-x64 true 7\n",[221],{"type":19,"tag":27,"props":222,"children":223},{"__ignoreMap":7},[224,266,273,281],{"type":19,"tag":87,"props":225,"children":226},{"class":89,"line":90},[227,231,235,240,245,250,256,261],{"type":19,"tag":87,"props":228,"children":229},{"style":104},[230],{"type":24,"value":32},{"type":19,"tag":87,"props":232,"children":233},{"style":110},[234],{"type":24,"value":195},{"type":19,"tag":87,"props":236,"children":237},{"style":110},[238],{"type":24,"value":239}," image",{"type":19,"tag":87,"props":241,"children":242},{"style":110},[243],{"type":24,"value":244}," list",{"type":19,"tag":87,"props":246,"children":247},{"style":208},[248],{"type":24,"value":249}," --public",{"type":19,"tag":87,"props":251,"children":253},{"style":252},"--shiki-default:#D73A49",[254],{"type":24,"value":255}," |",{"type":19,"tag":87,"props":257,"children":258},{"style":104},[259],{"type":24,"value":260}," grep",{"type":19,"tag":87,"props":262,"children":263},{"style":110},[264],{"type":24,"value":265}," ubuntu-22\n",{"type":19,"tag":87,"props":267,"children":268},{"class":89,"line":100},[269],{"type":19,"tag":87,"props":270,"children":271},{"emptyLinePlaceholder":125},[272],{"type":24,"value":128},{"type":19,"tag":87,"props":274,"children":275},{"class":89,"line":121},[276],{"type":19,"tag":87,"props":277,"children":278},{"style":94},[279],{"type":24,"value":280},"# 118857366 22.04 (LTS) x64 snapshot Ubuntu ubuntu-22-04-x64 true 7\n",{"type":19,"tag":87,"props":282,"children":283},{"class":89,"line":131},[284],{"type":19,"tag":87,"props":285,"children":286},{"style":94},[287],{"type":24,"value":288},"# 119383150 22.10 x64 snapshot Ubuntu ubuntu-22-10-x64 true 7\n",{"type":19,"tag":20,"props":290,"children":291},{},[292],{"type":24,"value":293},"And also the slug of the compute size:",{"type":19,"tag":77,"props":295,"children":297},{"className":79,"code":296,"language":81,"meta":7,"style":7},"doctl compute size list\n\n# Slug Description Memory VCPUs Disk Price Monthly Price Hourly\n# s-1vcpu-512mb-10gb Basic 512 1 10 4.00 0.005950\n# s-1vcpu-1gb Basic 1024 1 25 6.00 0.008930\n# s-1vcpu-1gb-amd Basic AMD 1024 1 25 7.00 0.010420\n# s-1vcpu-1gb-intel Basic Intel 1024 1 25 7.00 0.010420\n# s-1vcpu-2gb Basic 2048 1 50 12.00 0.017860\n# s-1vcpu-2gb-amd Basic AMD 2048 1 50 14.00 0.020830\n",[298],{"type":19,"tag":27,"props":299,"children":300},{"__ignoreMap":7},[301,322,329,337,345,353,362,371,380],{"type":19,"tag":87,"props":302,"children":303},{"class":89,"line":90},[304,308,312,317],{"type":19,"tag":87,"props":305,"children":306},{"style":104},[307],{"type":24,"value":32},{"type":19,"tag":87,"props":309,"children":310},{"style":110},[311],{"type":24,"value":195},{"type":19,"tag":87,"props":313,"children":314},{"style":110},[315],{"type":24,"value":316}," size",{"type":19,"tag":87,"props":318,"children":319},{"style":110},[320],{"type":24,"value":321}," list\n",{"type":19,"tag":87,"props":323,"children":324},{"class":89,"line":100},[325],{"type":19,"tag":87,"props":326,"children":327},{"emptyLinePlaceholder":125},[328],{"type":24,"value":128},{"type":19,"tag":87,"props":330,"children":331},{"class":89,"line":121},[332],{"type":19,"tag":87,"props":333,"children":334},{"style":94},[335],{"type":24,"value":336},"# Slug Description Memory VCPUs Disk Price Monthly Price Hourly\n",{"type":19,"tag":87,"props":338,"children":339},{"class":89,"line":131},[340],{"type":19,"tag":87,"props":341,"children":342},{"style":94},[343],{"type":24,"value":344},"# s-1vcpu-512mb-10gb Basic 512 1 10 4.00 0.005950\n",{"type":19,"tag":87,"props":346,"children":347},{"class":89,"line":140},[348],{"type":19,"tag":87,"props":349,"children":350},{"style":94},[351],{"type":24,"value":352},"# s-1vcpu-1gb Basic 1024 1 25 6.00 0.008930\n",{"type":19,"tag":87,"props":354,"children":356},{"class":89,"line":355},6,[357],{"type":19,"tag":87,"props":358,"children":359},{"style":94},[360],{"type":24,"value":361},"# s-1vcpu-1gb-amd Basic AMD 1024 1 25 7.00 0.010420\n",{"type":19,"tag":87,"props":363,"children":365},{"class":89,"line":364},7,[366],{"type":19,"tag":87,"props":367,"children":368},{"style":94},[369],{"type":24,"value":370},"# s-1vcpu-1gb-intel Basic Intel 1024 1 25 7.00 0.010420\n",{"type":19,"tag":87,"props":372,"children":374},{"class":89,"line":373},8,[375],{"type":19,"tag":87,"props":376,"children":377},{"style":94},[378],{"type":24,"value":379},"# s-1vcpu-2gb Basic 2048 1 50 12.00 0.017860\n",{"type":19,"tag":87,"props":381,"children":383},{"class":89,"line":382},9,[384],{"type":19,"tag":87,"props":385,"children":386},{"style":94},[387],{"type":24,"value":388},"# s-1vcpu-2gb-amd Basic AMD 2048 1 50 14.00 0.020830\n",{"type":19,"tag":20,"props":390,"children":391},{},[392,394,400],{"type":24,"value":393},"I've also configured a few SSH keys with Digital Ocean, and I can have the key (specified by ID) provisioned to the machine using the ",{"type":19,"tag":27,"props":395,"children":397},{"className":396},[],[398],{"type":24,"value":399},"--ssh-keys",{"type":24,"value":401}," flag.",{"type":19,"tag":77,"props":403,"children":405},{"className":79,"code":404,"language":81,"meta":7,"style":7},"doctl compute ssh-key list\n\n# ID Name FingerPrint\n# 1234 mini \u003Credacted>\n",[406],{"type":19,"tag":27,"props":407,"children":408},{"__ignoreMap":7},[409,429,436,444],{"type":19,"tag":87,"props":410,"children":411},{"class":89,"line":90},[412,416,420,425],{"type":19,"tag":87,"props":413,"children":414},{"style":104},[415],{"type":24,"value":32},{"type":19,"tag":87,"props":417,"children":418},{"style":110},[419],{"type":24,"value":195},{"type":19,"tag":87,"props":421,"children":422},{"style":110},[423],{"type":24,"value":424}," ssh-key",{"type":19,"tag":87,"props":426,"children":427},{"style":110},[428],{"type":24,"value":321},{"type":19,"tag":87,"props":430,"children":431},{"class":89,"line":100},[432],{"type":19,"tag":87,"props":433,"children":434},{"emptyLinePlaceholder":125},[435],{"type":24,"value":128},{"type":19,"tag":87,"props":437,"children":438},{"class":89,"line":121},[439],{"type":19,"tag":87,"props":440,"children":441},{"style":94},[442],{"type":24,"value":443},"# ID Name FingerPrint\n",{"type":19,"tag":87,"props":445,"children":446},{"class":89,"line":131},[447],{"type":19,"tag":87,"props":448,"children":449},{"style":94},[450],{"type":24,"value":451},"# 1234 mini \u003Credacted>\n",{"type":19,"tag":20,"props":453,"children":454},{},[455,457,463],{"type":24,"value":456},"Also, I wanted to install a few packages to the box upon creation, this can be done easily with the ",{"type":19,"tag":27,"props":458,"children":460},{"className":459},[],[461],{"type":24,"value":462},"--user-data-file",{"type":24,"value":464}," flag to run an initialization script.",{"type":19,"tag":77,"props":466,"children":468},{"className":79,"code":467,"language":81,"meta":7,"style":7},"echo 'apt install -y imagemagick zip' > bootstrap.sh\n",[469],{"type":19,"tag":27,"props":470,"children":471},{"__ignoreMap":7},[472],{"type":19,"tag":87,"props":473,"children":474},{"class":89,"line":90},[475,480,485,490],{"type":19,"tag":87,"props":476,"children":477},{"style":208},[478],{"type":24,"value":479},"echo",{"type":19,"tag":87,"props":481,"children":482},{"style":110},[483],{"type":24,"value":484}," 'apt install -y imagemagick zip'",{"type":19,"tag":87,"props":486,"children":487},{"style":252},[488],{"type":24,"value":489}," >",{"type":19,"tag":87,"props":491,"children":492},{"style":110},[493],{"type":24,"value":494}," bootstrap.sh\n",{"type":19,"tag":20,"props":496,"children":497},{},[498],{"type":24,"value":499},"Putting it all together, here is the simple command for creating a small compute instance!",{"type":19,"tag":77,"props":501,"children":503},{"className":79,"code":502,"language":81,"meta":7,"style":7},"doctl compute droplet create \\\n --image ubuntu-22-10-x64 \\\n --size s-1vcpu-512mb-10gb \\\n --region nyc1 \\\n --ssh-keys 1234 \\\n --user-data-file boostrap.sh \\\n ephemeral\n",[504],{"type":19,"tag":27,"props":505,"children":506},{"__ignoreMap":7},[507,531,548,565,582,599,616],{"type":19,"tag":87,"props":508,"children":509},{"class":89,"line":90},[510,514,518,522,526],{"type":19,"tag":87,"props":511,"children":512},{"style":104},[513],{"type":24,"value":32},{"type":19,"tag":87,"props":515,"children":516},{"style":110},[517],{"type":24,"value":195},{"type":19,"tag":87,"props":519,"children":520},{"style":110},[521],{"type":24,"value":200},{"type":19,"tag":87,"props":523,"children":524},{"style":110},[525],{"type":24,"value":205},{"type":19,"tag":87,"props":527,"children":528},{"style":208},[529],{"type":24,"value":530}," \\\n",{"type":19,"tag":87,"props":532,"children":533},{"class":89,"line":100},[534,539,544],{"type":19,"tag":87,"props":535,"children":536},{"style":208},[537],{"type":24,"value":538}," --image",{"type":19,"tag":87,"props":540,"children":541},{"style":110},[542],{"type":24,"value":543}," ubuntu-22-10-x64",{"type":19,"tag":87,"props":545,"children":546},{"style":208},[547],{"type":24,"value":530},{"type":19,"tag":87,"props":549,"children":550},{"class":89,"line":121},[551,556,561],{"type":19,"tag":87,"props":552,"children":553},{"style":208},[554],{"type":24,"value":555}," --size",{"type":19,"tag":87,"props":557,"children":558},{"style":110},[559],{"type":24,"value":560}," s-1vcpu-512mb-10gb",{"type":19,"tag":87,"props":562,"children":563},{"style":208},[564],{"type":24,"value":530},{"type":19,"tag":87,"props":566,"children":567},{"class":89,"line":131},[568,573,578],{"type":19,"tag":87,"props":569,"children":570},{"style":208},[571],{"type":24,"value":572}," --region",{"type":19,"tag":87,"props":574,"children":575},{"style":110},[576],{"type":24,"value":577}," nyc1",{"type":19,"tag":87,"props":579,"children":580},{"style":208},[581],{"type":24,"value":530},{"type":19,"tag":87,"props":583,"children":584},{"class":89,"line":140},[585,590,595],{"type":19,"tag":87,"props":586,"children":587},{"style":208},[588],{"type":24,"value":589}," --ssh-keys",{"type":19,"tag":87,"props":591,"children":592},{"style":208},[593],{"type":24,"value":594}," 1234",{"type":19,"tag":87,"props":596,"children":597},{"style":208},[598],{"type":24,"value":530},{"type":19,"tag":87,"props":600,"children":601},{"class":89,"line":355},[602,607,612],{"type":19,"tag":87,"props":603,"children":604},{"style":208},[605],{"type":24,"value":606}," --user-data-file",{"type":19,"tag":87,"props":608,"children":609},{"style":110},[610],{"type":24,"value":611}," boostrap.sh",{"type":19,"tag":87,"props":613,"children":614},{"style":208},[615],{"type":24,"value":530},{"type":19,"tag":87,"props":617,"children":618},{"class":89,"line":364},[619],{"type":19,"tag":87,"props":620,"children":621},{"style":110},[622],{"type":24,"value":623}," ephemeral\n",{"type":19,"tag":20,"props":625,"children":626},{},[627],{"type":24,"value":628},"Finally, I can connect, do my thing, and destroy the instance.",{"type":19,"tag":77,"props":630,"children":632},{"className":79,"code":631,"language":81,"meta":7,"style":7},"doctl compute ssh ephemeral\n",[633],{"type":19,"tag":27,"props":634,"children":635},{"__ignoreMap":7},[636],{"type":19,"tag":87,"props":637,"children":638},{"class":89,"line":90},[639,643,647,652],{"type":19,"tag":87,"props":640,"children":641},{"style":104},[642],{"type":24,"value":32},{"type":19,"tag":87,"props":644,"children":645},{"style":110},[646],{"type":24,"value":195},{"type":19,"tag":87,"props":648,"children":649},{"style":110},[650],{"type":24,"value":651}," ssh",{"type":19,"tag":87,"props":653,"children":654},{"style":110},[655],{"type":24,"value":656}," ephemeral\n",{"type":19,"tag":77,"props":658,"children":660},{"className":79,"code":659,"language":81,"meta":7,"style":7},"doctl compute droplet delete --force ephemeral\n",[661],{"type":19,"tag":27,"props":662,"children":663},{"__ignoreMap":7},[664],{"type":19,"tag":87,"props":665,"children":666},{"class":89,"line":90},[667,671,675,679,684,689],{"type":19,"tag":87,"props":668,"children":669},{"style":104},[670],{"type":24,"value":32},{"type":19,"tag":87,"props":672,"children":673},{"style":110},[674],{"type":24,"value":195},{"type":19,"tag":87,"props":676,"children":677},{"style":110},[678],{"type":24,"value":200},{"type":19,"tag":87,"props":680,"children":681},{"style":110},[682],{"type":24,"value":683}," delete",{"type":19,"tag":87,"props":685,"children":686},{"style":208},[687],{"type":24,"value":688}," --force",{"type":19,"tag":87,"props":690,"children":691},{"style":110},[692],{"type":24,"value":656},{"type":19,"tag":20,"props":694,"children":695},{},[696],{"type":24,"value":697},"All-in-all, I was up and running in about 20 minutes. What a handy utility!",{"type":19,"tag":699,"props":700,"children":701},"style",{},[702],{"type":24,"value":703},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":100,"depth":100,"links":705},[],"markdown","content:articles:doctl.md","content","articles/doctl.md","md",1727638398047] \ No newline at end of file diff --git a/articles/doctl/index.html b/articles/doctl/index.html index df52b0a1..fe370562 100644 --- a/articles/doctl/index.html +++ b/articles/doctl/index.html @@ -4,33 +4,32 @@ - - + + - - - - + + + + - - + - - - - - - - - - - - - - -

            Exploring the Digital Ocean `doctl` Utility

            I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean doctl command line utility. + + + + + + + + + + + + + +

            Exploring the Digital Ocean `doctl` Utility

            I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean doctl command line utility. This proved to be an extremely easy way to configure, create, connect, and destroy a Linux box, and I foresee myself using this service even more in the future.

            To start things off, I had to install and setup authentication to Digital Ocean. Doing this on my Mac machine, I opted to use Homebrew.

            # install `doctl`
             brew install doctl
            @@ -65,5 +64,5 @@
                 ephemeral
             

            Finally, I can connect, do my thing, and destroy the instance.

            doctl compute ssh ephemeral
             
            doctl compute droplet delete --force ephemeral
            -

            All-in-all, I was up and running in about 20 minutes. What a handy utility!

            - \ No newline at end of file +

            All-in-all, I was up and running in about 20 minutes. What a handy utility!

            + \ No newline at end of file diff --git a/articles/fennel-initial-exploration/_payload.json b/articles/fennel-initial-exploration/_payload.json index fb34e3f3..10f43a2e 100644 --- a/articles/fennel-initial-exploration/_payload.json +++ b/articles/fennel-initial-exploration/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":1106},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"draft":6,"date":10,"tags":11,"categories":15,"cover_image":16,"excerpt":17,"body":27,"_type":1100,"_id":1101,"_source":1102,"_file":1103,"_stem":1104,"_extension":1105},"/articles/fennel-initial-exploration","articles",false,"","Impressions of Fennel with Hammerspoon","A while back I read an introductory book on Lisp programming titled, \"The Little\nSchemer\". This book opened my mind to new (to me) programming paradigms, and left me\nwith a strong desire to find a way to incorporate Lisp programming into my every day\nlife. It took some time, but I believe I've found what I've been looking for: Fennel.","2023-10-22",[12,13,14],"lisp","hammerspoon","fennel",[12],"/images/dall-e-fennel-hammer.jpeg",{"type":18,"children":19},"root",[20],{"type":21,"tag":22,"props":23,"children":24},"element","p",{},[25],{"type":26,"value":9},"text",{"type":18,"children":28,"toc":1094},[29,33,67,74,88,94,125,157,170,199,422,428,458,536,598,611,917,1039,1052,1058,1063,1077,1088],{"type":21,"tag":22,"props":30,"children":31},{},[32],{"type":26,"value":9},{"type":21,"tag":22,"props":34,"children":35},{},[36,38,47,49,56,58,65],{"type":26,"value":37},"The ",{"type":21,"tag":39,"props":40,"children":44},"a",{"href":41,"rel":42},"https://fennel-lang.org/",[43],"nofollow",[45],{"type":26,"value":46},"Fennel",{"type":26,"value":48}," programming language is a dialect of Lisp that boasts compatibility with\nLua, and it just so happens that two of my favorite applications are configured with\nexactly that language: ",{"type":21,"tag":39,"props":50,"children":53},{"href":51,"rel":52},"https://www.hammerspoon.org/",[43],[54],{"type":26,"value":55},"Hammerspoon",{"type":26,"value":57},", and ",{"type":21,"tag":39,"props":59,"children":62},{"href":60,"rel":61},"https://neovim.io/",[43],[63],{"type":26,"value":64},"Neovim",{"type":26,"value":66},".",{"type":21,"tag":68,"props":69,"children":71},"h2",{"id":70},"initial-observations",[72],{"type":26,"value":73},"Initial Observations",{"type":21,"tag":22,"props":75,"children":76},{},[77,79,86],{"type":26,"value":78},"To initially explore Fennel, I wanted to start small. My Hammerspoon configuration\nconsists of 7 ",{"type":21,"tag":39,"props":80,"children":83},{"href":81,"rel":82},"https://github.com/cmpadden/dotfiles/tree/795749fa17e1310bb001bb7deaa22be8689f0027/hammerspoon/.hammerspoon/modules",[43],[84],{"type":26,"value":85},"modules",{"type":26,"value":87}," that I use for operations such as: launching applications,\nmanaging windows, keeping my computer from going to sleep, and general operating system\nautomation. So the plan is to translate these modules into Fennel, while maintaining\nwithout breaking the existing functionality. However, at this point, I wasn't even sure\nhow to embed Fennel into my project...",{"type":21,"tag":68,"props":89,"children":91},{"id":90},"integrating-fennel-with-hammerspoon",[92],{"type":26,"value":93},"Integrating Fennel with Hammerspoon",{"type":21,"tag":22,"props":95,"children":96},{},[97,99,106,108,115,117,123],{"type":26,"value":98},"While official documentation exists describing how to ",{"type":21,"tag":39,"props":100,"children":103},{"href":101,"rel":102},"https://fennel-lang.org/setup#embedding-fennel",[43],[104],{"type":26,"value":105},"embed fennel",{"type":26,"value":107}," into your\nproject; it didn't provide me with enough clarity to know my next steps on integrating\nit with Hammerspoon. I found a few resources online demonstrating how to extend the\n",{"type":21,"tag":109,"props":110,"children":112},"code",{"className":111},[],[113],{"type":26,"value":114},"package.path",{"type":26,"value":116}," and ",{"type":21,"tag":109,"props":118,"children":120},{"className":119},[],[121],{"type":26,"value":122},"package.cpath",{"type":26,"value":124}," properties in Lua, but I was unable to get this to\nwork.",{"type":21,"tag":126,"props":127,"children":128},"ul",{},[129,139,148],{"type":21,"tag":130,"props":131,"children":132},"li",{},[133],{"type":21,"tag":39,"props":134,"children":137},{"href":135,"rel":136},"https://blog.exupero.org/hammerspoon-with-fennel/",[43],[138],{"type":26,"value":135},{"type":21,"tag":130,"props":140,"children":141},{},[142],{"type":21,"tag":39,"props":143,"children":146},{"href":144,"rel":145},"https://github.com/Hammerspoon/hammerspoon/issues/2377#issuecomment-636331435",[43],[147],{"type":26,"value":144},{"type":21,"tag":130,"props":149,"children":150},{},[151],{"type":21,"tag":39,"props":152,"children":155},{"href":153,"rel":154},"https://github.com/agzam/spacehammer/blob/master/init.lua",[43],[156],{"type":26,"value":153},{"type":21,"tag":22,"props":158,"children":159},{},[160,162,168],{"type":26,"value":161},"Ultimately, I opted to include the ",{"type":21,"tag":109,"props":163,"children":165},{"className":164},[],[166],{"type":26,"value":167},"fennel.lua",{"type":26,"value":169}," file to my Hammerspoon configuration,\nand while not ideal, it does make the configuration nicely self-contained. I'll leave it\nas a future task to include the module installed with LuaRocks.",{"type":21,"tag":22,"props":171,"children":172},{},[173,175,181,183,189,191,197],{"type":26,"value":174},"With Fennel now included in my Hammerspoon configuration, all I need to do is configure\nthe ",{"type":21,"tag":109,"props":176,"children":178},{"className":177},[],[179],{"type":26,"value":180},"fennel.path",{"type":26,"value":182}," to point to the ",{"type":21,"tag":109,"props":184,"children":186},{"className":185},[],[187],{"type":26,"value":188},"*.fnl",{"type":26,"value":190}," files in the ",{"type":21,"tag":109,"props":192,"children":194},{"className":193},[],[195],{"type":26,"value":196},".hammerspoon/",{"type":26,"value":198}," directory, and\nttranslating these modules can begin!",{"type":21,"tag":200,"props":201,"children":205},"pre",{"className":202,"code":203,"language":204,"meta":7,"style":7},"language-lua shiki shiki-themes github-light","-- init.lua\n\nlocal fennel = require('fennel')\n\nfennel.path = package.path .. \";\" .. os.getenv(\"HOME\") .. \"/.hammerspoon/?.fnl\"\n\ntable.insert(package.loaders or package.searchers, fennel.searcher)\n\nrequire 'main'\n","lua",[206],{"type":21,"tag":109,"props":207,"children":208},{"__ignoreMap":7},[209,221,231,274,282,350,358,400,408],{"type":21,"tag":210,"props":211,"children":214},"span",{"class":212,"line":213},"line",1,[215],{"type":21,"tag":210,"props":216,"children":218},{"style":217},"--shiki-default:#6A737D",[219],{"type":26,"value":220},"-- init.lua\n",{"type":21,"tag":210,"props":222,"children":224},{"class":212,"line":223},2,[225],{"type":21,"tag":210,"props":226,"children":228},{"emptyLinePlaceholder":227},true,[229],{"type":26,"value":230},"\n",{"type":21,"tag":210,"props":232,"children":234},{"class":212,"line":233},3,[235,241,247,252,258,263,269],{"type":21,"tag":210,"props":236,"children":238},{"style":237},"--shiki-default:#D73A49",[239],{"type":26,"value":240},"local",{"type":21,"tag":210,"props":242,"children":244},{"style":243},"--shiki-default:#24292E",[245],{"type":26,"value":246}," fennel ",{"type":21,"tag":210,"props":248,"children":249},{"style":237},[250],{"type":26,"value":251},"=",{"type":21,"tag":210,"props":253,"children":255},{"style":254},"--shiki-default:#005CC5",[256],{"type":26,"value":257}," require",{"type":21,"tag":210,"props":259,"children":260},{"style":243},[261],{"type":26,"value":262},"(",{"type":21,"tag":210,"props":264,"children":266},{"style":265},"--shiki-default:#032F62",[267],{"type":26,"value":268},"'fennel'",{"type":21,"tag":210,"props":270,"children":271},{"style":243},[272],{"type":26,"value":273},")\n",{"type":21,"tag":210,"props":275,"children":277},{"class":212,"line":276},4,[278],{"type":21,"tag":210,"props":279,"children":280},{"emptyLinePlaceholder":227},[281],{"type":26,"value":230},{"type":21,"tag":210,"props":283,"children":285},{"class":212,"line":284},5,[286,291,297,302,307,312,317,322,327,331,336,341,345],{"type":21,"tag":210,"props":287,"children":288},{"style":243},[289],{"type":26,"value":290},"fennel.",{"type":21,"tag":210,"props":292,"children":294},{"style":293},"--shiki-default:#6F42C1",[295],{"type":26,"value":296},"path",{"type":21,"tag":210,"props":298,"children":299},{"style":237},[300],{"type":26,"value":301}," =",{"type":21,"tag":210,"props":303,"children":304},{"style":254},[305],{"type":26,"value":306}," package.path",{"type":21,"tag":210,"props":308,"children":309},{"style":237},[310],{"type":26,"value":311}," ..",{"type":21,"tag":210,"props":313,"children":314},{"style":265},[315],{"type":26,"value":316}," \";\" ",{"type":21,"tag":210,"props":318,"children":319},{"style":237},[320],{"type":26,"value":321},"..",{"type":21,"tag":210,"props":323,"children":324},{"style":254},[325],{"type":26,"value":326}," os.getenv",{"type":21,"tag":210,"props":328,"children":329},{"style":243},[330],{"type":26,"value":262},{"type":21,"tag":210,"props":332,"children":333},{"style":265},[334],{"type":26,"value":335},"\"HOME\"",{"type":21,"tag":210,"props":337,"children":338},{"style":243},[339],{"type":26,"value":340},") ",{"type":21,"tag":210,"props":342,"children":343},{"style":237},[344],{"type":26,"value":321},{"type":21,"tag":210,"props":346,"children":347},{"style":265},[348],{"type":26,"value":349}," \"/.hammerspoon/?.fnl\"\n",{"type":21,"tag":210,"props":351,"children":353},{"class":212,"line":352},6,[354],{"type":21,"tag":210,"props":355,"children":356},{"emptyLinePlaceholder":227},[357],{"type":26,"value":230},{"type":21,"tag":210,"props":359,"children":361},{"class":212,"line":360},7,[362,367,371,376,381,386,391,396],{"type":21,"tag":210,"props":363,"children":364},{"style":254},[365],{"type":26,"value":366},"table.insert",{"type":21,"tag":210,"props":368,"children":369},{"style":243},[370],{"type":26,"value":262},{"type":21,"tag":210,"props":372,"children":373},{"style":254},[374],{"type":26,"value":375},"package.loaders",{"type":21,"tag":210,"props":377,"children":378},{"style":237},[379],{"type":26,"value":380}," or",{"type":21,"tag":210,"props":382,"children":383},{"style":254},[384],{"type":26,"value":385}," package.searchers",{"type":21,"tag":210,"props":387,"children":388},{"style":243},[389],{"type":26,"value":390},", fennel.",{"type":21,"tag":210,"props":392,"children":393},{"style":293},[394],{"type":26,"value":395},"searcher",{"type":21,"tag":210,"props":397,"children":398},{"style":243},[399],{"type":26,"value":273},{"type":21,"tag":210,"props":401,"children":403},{"class":212,"line":402},8,[404],{"type":21,"tag":210,"props":405,"children":406},{"emptyLinePlaceholder":227},[407],{"type":26,"value":230},{"type":21,"tag":210,"props":409,"children":411},{"class":212,"line":410},9,[412,417],{"type":21,"tag":210,"props":413,"children":414},{"style":254},[415],{"type":26,"value":416},"require",{"type":21,"tag":210,"props":418,"children":419},{"style":265},[420],{"type":26,"value":421}," 'main'\n",{"type":21,"tag":68,"props":423,"children":425},{"id":424},"translating-lua-to-fennel",[426],{"type":26,"value":427},"Translating Lua to Fennel",{"type":21,"tag":22,"props":429,"children":430},{},[431,433,440,442,448,450,456],{"type":26,"value":432},"As a Fennel novice, I was happy to see that the Fennel project provides an online\ncross-compiler for Lua and Fennel called ",{"type":21,"tag":39,"props":434,"children":437},{"href":435,"rel":436},"https://fennel-lang.org/see",[43],[438],{"type":26,"value":439},"anti-fennel",{"type":26,"value":441},", and while it can generate some\nstrange-looking Fennel code, it was an extremely useful tool for me to get\nup-and-running right away. For example, by pasting the simple ",{"type":21,"tag":109,"props":443,"children":445},{"className":444},[],[446],{"type":26,"value":447},"sleep",{"type":26,"value":449}," function\nfrom the ",{"type":21,"tag":109,"props":451,"children":453},{"className":452},[],[454],{"type":26,"value":455},"helpers",{"type":26,"value":457}," module into the compiler:",{"type":21,"tag":200,"props":459,"children":461},{"className":202,"code":460,"language":204,"meta":7,"style":7},"function sleep(ms)\n os.execute(\"sleep \" .. tonumber(ms) / 1000)\nend\n",[462],{"type":21,"tag":109,"props":463,"children":464},{"__ignoreMap":7},[465,483,528],{"type":21,"tag":210,"props":466,"children":467},{"class":212,"line":213},[468,473,478],{"type":21,"tag":210,"props":469,"children":470},{"style":237},[471],{"type":26,"value":472},"function",{"type":21,"tag":210,"props":474,"children":475},{"style":293},[476],{"type":26,"value":477}," sleep",{"type":21,"tag":210,"props":479,"children":480},{"style":243},[481],{"type":26,"value":482},"(ms)\n",{"type":21,"tag":210,"props":484,"children":485},{"class":212,"line":223},[486,491,495,500,504,509,514,519,524],{"type":21,"tag":210,"props":487,"children":488},{"style":254},[489],{"type":26,"value":490}," os.execute",{"type":21,"tag":210,"props":492,"children":493},{"style":243},[494],{"type":26,"value":262},{"type":21,"tag":210,"props":496,"children":497},{"style":265},[498],{"type":26,"value":499},"\"sleep \" ",{"type":21,"tag":210,"props":501,"children":502},{"style":237},[503],{"type":26,"value":321},{"type":21,"tag":210,"props":505,"children":506},{"style":254},[507],{"type":26,"value":508}," tonumber",{"type":21,"tag":210,"props":510,"children":511},{"style":243},[512],{"type":26,"value":513},"(ms) ",{"type":21,"tag":210,"props":515,"children":516},{"style":237},[517],{"type":26,"value":518},"/",{"type":21,"tag":210,"props":520,"children":521},{"style":254},[522],{"type":26,"value":523}," 1000",{"type":21,"tag":210,"props":525,"children":526},{"style":243},[527],{"type":26,"value":273},{"type":21,"tag":210,"props":529,"children":530},{"class":212,"line":233},[531],{"type":21,"tag":210,"props":532,"children":533},{"style":237},[534],{"type":26,"value":535},"end\n",{"type":21,"tag":200,"props":537,"children":540},{"className":538,"code":539,"language":12,"meta":7,"style":7},"language-lisp shiki shiki-themes github-light","(fn sleep [ms]\n (os.execute (.. \"sleep \" (/ (tonumber ms) 1000))))\n",[541],{"type":21,"tag":109,"props":542,"children":543},{"__ignoreMap":7},[544,561],{"type":21,"tag":210,"props":545,"children":546},{"class":212,"line":213},[547,552,556],{"type":21,"tag":210,"props":548,"children":549},{"style":243},[550],{"type":26,"value":551},"(fn ",{"type":21,"tag":210,"props":553,"children":554},{"style":254},[555],{"type":26,"value":447},{"type":21,"tag":210,"props":557,"children":558},{"style":243},[559],{"type":26,"value":560}," [ms]\n",{"type":21,"tag":210,"props":562,"children":563},{"class":212,"line":223},[564,569,574,579,583,588,593],{"type":21,"tag":210,"props":565,"children":566},{"style":243},[567],{"type":26,"value":568}," (os.execute (.. ",{"type":21,"tag":210,"props":570,"children":571},{"style":265},[572],{"type":26,"value":573},"\"sleep \"",{"type":21,"tag":210,"props":575,"children":576},{"style":243},[577],{"type":26,"value":578}," (",{"type":21,"tag":210,"props":580,"children":581},{"style":254},[582],{"type":26,"value":518},{"type":21,"tag":210,"props":584,"children":585},{"style":243},[586],{"type":26,"value":587}," (tonumber ms) ",{"type":21,"tag":210,"props":589,"children":590},{"style":254},[591],{"type":26,"value":592},"1000",{"type":21,"tag":210,"props":594,"children":595},{"style":243},[596],{"type":26,"value":597},"))))\n",{"type":21,"tag":22,"props":599,"children":600},{},[601,603,609],{"type":26,"value":602},"As another example, here is the output for my ",{"type":21,"tag":604,"props":605,"children":606},"em",{},[607],{"type":26,"value":608},"caffeine",{"type":26,"value":610}," toggle:",{"type":21,"tag":200,"props":612,"children":614},{"className":202,"code":613,"language":204,"meta":7,"style":7},"hs.hotkey.bind(HYPER, \"0\", function()\n hs.caffeinate.toggle(\"displayIdle\")\n if hs.caffeinate.get(\"displayIdle\") then\n helpers:show(\"Caffeine Enabled\", nil, helpers.styles.success, helpers.assets.check)\n else\n helpers:show(\"Caffeine Disabled\", nil, helpers.styles.error, helpers.assets.ban)\n end\nend)\n",[615],{"type":21,"tag":109,"props":616,"children":617},{"__ignoreMap":7},[618,664,699,742,819,827,897,905],{"type":21,"tag":210,"props":619,"children":620},{"class":212,"line":213},[621,626,631,635,640,645,650,655,659],{"type":21,"tag":210,"props":622,"children":623},{"style":243},[624],{"type":26,"value":625},"hs.",{"type":21,"tag":210,"props":627,"children":628},{"style":293},[629],{"type":26,"value":630},"hotkey",{"type":21,"tag":210,"props":632,"children":633},{"style":243},[634],{"type":26,"value":66},{"type":21,"tag":210,"props":636,"children":637},{"style":254},[638],{"type":26,"value":639},"bind",{"type":21,"tag":210,"props":641,"children":642},{"style":243},[643],{"type":26,"value":644},"(HYPER, ",{"type":21,"tag":210,"props":646,"children":647},{"style":265},[648],{"type":26,"value":649},"\"0\"",{"type":21,"tag":210,"props":651,"children":652},{"style":243},[653],{"type":26,"value":654},", ",{"type":21,"tag":210,"props":656,"children":657},{"style":237},[658],{"type":26,"value":472},{"type":21,"tag":210,"props":660,"children":661},{"style":243},[662],{"type":26,"value":663},"()\n",{"type":21,"tag":210,"props":665,"children":666},{"class":212,"line":223},[667,672,677,681,686,690,695],{"type":21,"tag":210,"props":668,"children":669},{"style":243},[670],{"type":26,"value":671}," hs.",{"type":21,"tag":210,"props":673,"children":674},{"style":293},[675],{"type":26,"value":676},"caffeinate",{"type":21,"tag":210,"props":678,"children":679},{"style":243},[680],{"type":26,"value":66},{"type":21,"tag":210,"props":682,"children":683},{"style":254},[684],{"type":26,"value":685},"toggle",{"type":21,"tag":210,"props":687,"children":688},{"style":243},[689],{"type":26,"value":262},{"type":21,"tag":210,"props":691,"children":692},{"style":265},[693],{"type":26,"value":694},"\"displayIdle\"",{"type":21,"tag":210,"props":696,"children":697},{"style":243},[698],{"type":26,"value":273},{"type":21,"tag":210,"props":700,"children":701},{"class":212,"line":233},[702,707,712,716,720,725,729,733,737],{"type":21,"tag":210,"props":703,"children":704},{"style":237},[705],{"type":26,"value":706}," if",{"type":21,"tag":210,"props":708,"children":709},{"style":243},[710],{"type":26,"value":711}," hs.",{"type":21,"tag":210,"props":713,"children":714},{"style":293},[715],{"type":26,"value":676},{"type":21,"tag":210,"props":717,"children":718},{"style":243},[719],{"type":26,"value":66},{"type":21,"tag":210,"props":721,"children":722},{"style":254},[723],{"type":26,"value":724},"get",{"type":21,"tag":210,"props":726,"children":727},{"style":243},[728],{"type":26,"value":262},{"type":21,"tag":210,"props":730,"children":731},{"style":265},[732],{"type":26,"value":694},{"type":21,"tag":210,"props":734,"children":735},{"style":243},[736],{"type":26,"value":340},{"type":21,"tag":210,"props":738,"children":739},{"style":237},[740],{"type":26,"value":741},"then\n",{"type":21,"tag":210,"props":743,"children":744},{"class":212,"line":276},[745,750,755,760,764,769,773,778,783,788,792,797,801,806,810,815],{"type":21,"tag":210,"props":746,"children":747},{"style":293},[748],{"type":26,"value":749}," helpers",{"type":21,"tag":210,"props":751,"children":752},{"style":243},[753],{"type":26,"value":754},":",{"type":21,"tag":210,"props":756,"children":757},{"style":254},[758],{"type":26,"value":759},"show",{"type":21,"tag":210,"props":761,"children":762},{"style":243},[763],{"type":26,"value":262},{"type":21,"tag":210,"props":765,"children":766},{"style":265},[767],{"type":26,"value":768},"\"Caffeine Enabled\"",{"type":21,"tag":210,"props":770,"children":771},{"style":243},[772],{"type":26,"value":654},{"type":21,"tag":210,"props":774,"children":775},{"style":254},[776],{"type":26,"value":777},"nil",{"type":21,"tag":210,"props":779,"children":780},{"style":243},[781],{"type":26,"value":782},", helpers.",{"type":21,"tag":210,"props":784,"children":785},{"style":293},[786],{"type":26,"value":787},"styles",{"type":21,"tag":210,"props":789,"children":790},{"style":243},[791],{"type":26,"value":66},{"type":21,"tag":210,"props":793,"children":794},{"style":293},[795],{"type":26,"value":796},"success",{"type":21,"tag":210,"props":798,"children":799},{"style":243},[800],{"type":26,"value":782},{"type":21,"tag":210,"props":802,"children":803},{"style":293},[804],{"type":26,"value":805},"assets",{"type":21,"tag":210,"props":807,"children":808},{"style":243},[809],{"type":26,"value":66},{"type":21,"tag":210,"props":811,"children":812},{"style":293},[813],{"type":26,"value":814},"check",{"type":21,"tag":210,"props":816,"children":817},{"style":243},[818],{"type":26,"value":273},{"type":21,"tag":210,"props":820,"children":821},{"class":212,"line":284},[822],{"type":21,"tag":210,"props":823,"children":824},{"style":237},[825],{"type":26,"value":826}," else\n",{"type":21,"tag":210,"props":828,"children":829},{"class":212,"line":352},[830,834,838,842,846,851,855,859,863,867,871,876,880,884,888,893],{"type":21,"tag":210,"props":831,"children":832},{"style":293},[833],{"type":26,"value":749},{"type":21,"tag":210,"props":835,"children":836},{"style":243},[837],{"type":26,"value":754},{"type":21,"tag":210,"props":839,"children":840},{"style":254},[841],{"type":26,"value":759},{"type":21,"tag":210,"props":843,"children":844},{"style":243},[845],{"type":26,"value":262},{"type":21,"tag":210,"props":847,"children":848},{"style":265},[849],{"type":26,"value":850},"\"Caffeine Disabled\"",{"type":21,"tag":210,"props":852,"children":853},{"style":243},[854],{"type":26,"value":654},{"type":21,"tag":210,"props":856,"children":857},{"style":254},[858],{"type":26,"value":777},{"type":21,"tag":210,"props":860,"children":861},{"style":243},[862],{"type":26,"value":782},{"type":21,"tag":210,"props":864,"children":865},{"style":293},[866],{"type":26,"value":787},{"type":21,"tag":210,"props":868,"children":869},{"style":243},[870],{"type":26,"value":66},{"type":21,"tag":210,"props":872,"children":873},{"style":293},[874],{"type":26,"value":875},"error",{"type":21,"tag":210,"props":877,"children":878},{"style":243},[879],{"type":26,"value":782},{"type":21,"tag":210,"props":881,"children":882},{"style":293},[883],{"type":26,"value":805},{"type":21,"tag":210,"props":885,"children":886},{"style":243},[887],{"type":26,"value":66},{"type":21,"tag":210,"props":889,"children":890},{"style":293},[891],{"type":26,"value":892},"ban",{"type":21,"tag":210,"props":894,"children":895},{"style":243},[896],{"type":26,"value":273},{"type":21,"tag":210,"props":898,"children":899},{"class":212,"line":360},[900],{"type":21,"tag":210,"props":901,"children":902},{"style":237},[903],{"type":26,"value":904}," end\n",{"type":21,"tag":210,"props":906,"children":907},{"class":212,"line":402},[908,913],{"type":21,"tag":210,"props":909,"children":910},{"style":237},[911],{"type":26,"value":912},"end",{"type":21,"tag":210,"props":914,"children":915},{"style":243},[916],{"type":26,"value":273},{"type":21,"tag":200,"props":918,"children":920},{"className":538,"code":919,"language":12,"meta":7,"style":7},"(hs.hotkey.bind HYPER :0\n (fn [] (hs.caffeinate.toggle :displayIdle)\n (if (hs.caffeinate.get :displayIdle)\n (helpers:show \"Caffeine Enabled\" nil helpers.styles.success helpers.assets.check)\n (helpers:show \"Caffeine Disabled\" nil helpers.styles.error helpers.assets.ban)))) \n",[921],{"type":21,"tag":109,"props":922,"children":923},{"__ignoreMap":7},[924,937,954,980,1011],{"type":21,"tag":210,"props":925,"children":926},{"class":212,"line":213},[927,932],{"type":21,"tag":210,"props":928,"children":929},{"style":243},[930],{"type":26,"value":931},"(hs.hotkey.bind HYPER ",{"type":21,"tag":210,"props":933,"children":934},{"style":293},[935],{"type":26,"value":936},":0\n",{"type":21,"tag":210,"props":938,"children":939},{"class":212,"line":223},[940,945,950],{"type":21,"tag":210,"props":941,"children":942},{"style":243},[943],{"type":26,"value":944}," (fn [] (hs.caffeinate.toggle ",{"type":21,"tag":210,"props":946,"children":947},{"style":293},[948],{"type":26,"value":949},":displayIdle",{"type":21,"tag":210,"props":951,"children":952},{"style":243},[953],{"type":26,"value":273},{"type":21,"tag":210,"props":955,"children":956},{"class":212,"line":233},[957,962,967,972,976],{"type":21,"tag":210,"props":958,"children":959},{"style":243},[960],{"type":26,"value":961}," (",{"type":21,"tag":210,"props":963,"children":964},{"style":237},[965],{"type":26,"value":966},"if",{"type":21,"tag":210,"props":968,"children":969},{"style":243},[970],{"type":26,"value":971}," (hs.caffeinate.get ",{"type":21,"tag":210,"props":973,"children":974},{"style":293},[975],{"type":26,"value":949},{"type":21,"tag":210,"props":977,"children":978},{"style":243},[979],{"type":26,"value":273},{"type":21,"tag":210,"props":981,"children":982},{"class":212,"line":276},[983,988,992,997,1001,1006],{"type":21,"tag":210,"props":984,"children":985},{"style":243},[986],{"type":26,"value":987}," (",{"type":21,"tag":210,"props":989,"children":990},{"style":254},[991],{"type":26,"value":455},{"type":21,"tag":210,"props":993,"children":994},{"style":243},[995],{"type":26,"value":996},":show ",{"type":21,"tag":210,"props":998,"children":999},{"style":265},[1000],{"type":26,"value":768},{"type":21,"tag":210,"props":1002,"children":1003},{"style":254},[1004],{"type":26,"value":1005}," nil",{"type":21,"tag":210,"props":1007,"children":1008},{"style":243},[1009],{"type":26,"value":1010}," helpers.styles.success helpers.assets.check)\n",{"type":21,"tag":210,"props":1012,"children":1013},{"class":212,"line":284},[1014,1018,1022,1026,1030,1034],{"type":21,"tag":210,"props":1015,"children":1016},{"style":243},[1017],{"type":26,"value":987},{"type":21,"tag":210,"props":1019,"children":1020},{"style":254},[1021],{"type":26,"value":455},{"type":21,"tag":210,"props":1023,"children":1024},{"style":243},[1025],{"type":26,"value":996},{"type":21,"tag":210,"props":1027,"children":1028},{"style":265},[1029],{"type":26,"value":850},{"type":21,"tag":210,"props":1031,"children":1032},{"style":254},[1033],{"type":26,"value":1005},{"type":21,"tag":210,"props":1035,"children":1036},{"style":243},[1037],{"type":26,"value":1038}," helpers.styles.error helpers.assets.ban))))\n",{"type":21,"tag":22,"props":1040,"children":1041},{},[1042,1044,1050],{"type":26,"value":1043},"This was especially helpful for more gnarly modules like the ",{"type":21,"tag":109,"props":1045,"children":1047},{"className":1046},[],[1048],{"type":26,"value":1049},"window",{"type":26,"value":1051}," module used for\nwindow management, and seeing the Lua and Fennel code side-by-side was a kick starter in\nlearning the language!",{"type":21,"tag":68,"props":1053,"children":1055},{"id":1054},"next-steps",[1056],{"type":26,"value":1057},"Next Steps",{"type":21,"tag":22,"props":1059,"children":1060},{},[1061],{"type":26,"value":1062},"While my Fennel Hammerspoon configuration now works with parity to its Lua counterpart,\nI have not yet added new features or modules. I look forward to writing new Fennel code,\nand deepen my understanding of Lisp and the Fennel programming language.",{"type":21,"tag":22,"props":1064,"children":1065},{},[1066,1068,1075],{"type":26,"value":1067},"Additionally, before beginning this endeavor, I was already aware of projects like\n",{"type":21,"tag":39,"props":1069,"children":1072},{"href":1070,"rel":1071},"https://github.com/agzam/spacehammer",[43],[1073],{"type":26,"value":1074},"spacehammer",{"type":26,"value":1076},"; a wildly impressive Hammerspoon configuration written in Fennel, but,\nI wanted to start small and learn the integration myself. However, with the basics out\nof the way, I hope to explore this project further, and seek lessons-learned for the\nconfiguration of my own.",{"type":21,"tag":22,"props":1078,"children":1079},{},[1080,1082],{"type":26,"value":1081},"The full pull-request for translating my Lua Hammerspoon configuration to Fennel can be\nfound here: ",{"type":21,"tag":39,"props":1083,"children":1086},{"href":1084,"rel":1085},"https://github.com/cmpadden/dotfiles/pull/19/files",[43],[1087],{"type":26,"value":1084},{"type":21,"tag":1089,"props":1090,"children":1091},"style",{},[1092],{"type":26,"value":1093},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":223,"depth":223,"links":1095},[1096,1097,1098,1099],{"id":70,"depth":223,"text":73},{"id":90,"depth":223,"text":93},{"id":424,"depth":223,"text":427},{"id":1054,"depth":223,"text":1057},"markdown","content:articles:fennel-initial-exploration.md","content","articles/fennel-initial-exploration.md","articles/fennel-initial-exploration","md",1726174739506] \ No newline at end of file +[{"data":1,"prerenderedAt":1079},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"draft":6,"date":10,"tags":11,"categories":15,"cover_image":16,"excerpt":17,"body":27,"_type":1074,"_id":1075,"_source":1076,"_file":1077,"_extension":1078},"/articles/fennel-initial-exploration","articles",false,"","Impressions of Fennel with Hammerspoon","A while back I read an introductory book on Lisp programming titled, \"The Little\nSchemer\". This book opened my mind to new (to me) programming paradigms, and left me\nwith a strong desire to find a way to incorporate Lisp programming into my every day\nlife. It took some time, but I believe I've found what I've been looking for: Fennel.","2023-10-22",[12,13,14],"lisp","hammerspoon","fennel",[12],"/images/dall-e-fennel-hammer.jpeg",{"type":18,"children":19},"root",[20],{"type":21,"tag":22,"props":23,"children":24},"element","p",{},[25],{"type":26,"value":9},"text",{"type":18,"children":28,"toc":1068},[29,33,67,74,88,94,125,157,170,199,422,428,458,536,589,602,908,1013,1026,1032,1037,1051,1062],{"type":21,"tag":22,"props":30,"children":31},{},[32],{"type":26,"value":9},{"type":21,"tag":22,"props":34,"children":35},{},[36,38,47,49,56,58,65],{"type":26,"value":37},"The ",{"type":21,"tag":39,"props":40,"children":44},"a",{"href":41,"rel":42},"https://fennel-lang.org/",[43],"nofollow",[45],{"type":26,"value":46},"Fennel",{"type":26,"value":48}," programming language is a dialect of Lisp that boasts compatibility with\nLua, and it just so happens that two of my favorite applications are configured with\nexactly that language: ",{"type":21,"tag":39,"props":50,"children":53},{"href":51,"rel":52},"https://www.hammerspoon.org/",[43],[54],{"type":26,"value":55},"Hammerspoon",{"type":26,"value":57},", and ",{"type":21,"tag":39,"props":59,"children":62},{"href":60,"rel":61},"https://neovim.io/",[43],[63],{"type":26,"value":64},"Neovim",{"type":26,"value":66},".",{"type":21,"tag":68,"props":69,"children":71},"h2",{"id":70},"initial-observations",[72],{"type":26,"value":73},"Initial Observations",{"type":21,"tag":22,"props":75,"children":76},{},[77,79,86],{"type":26,"value":78},"To initially explore Fennel, I wanted to start small. My Hammerspoon configuration\nconsists of 7 ",{"type":21,"tag":39,"props":80,"children":83},{"href":81,"rel":82},"https://github.com/cmpadden/dotfiles/tree/795749fa17e1310bb001bb7deaa22be8689f0027/hammerspoon/.hammerspoon/modules",[43],[84],{"type":26,"value":85},"modules",{"type":26,"value":87}," that I use for operations such as: launching applications,\nmanaging windows, keeping my computer from going to sleep, and general operating system\nautomation. So the plan is to translate these modules into Fennel, while maintaining\nwithout breaking the existing functionality. However, at this point, I wasn't even sure\nhow to embed Fennel into my project...",{"type":21,"tag":68,"props":89,"children":91},{"id":90},"integrating-fennel-with-hammerspoon",[92],{"type":26,"value":93},"Integrating Fennel with Hammerspoon",{"type":21,"tag":22,"props":95,"children":96},{},[97,99,106,108,115,117,123],{"type":26,"value":98},"While official documentation exists describing how to ",{"type":21,"tag":39,"props":100,"children":103},{"href":101,"rel":102},"https://fennel-lang.org/setup#embedding-fennel",[43],[104],{"type":26,"value":105},"embed fennel",{"type":26,"value":107}," into your\nproject; it didn't provide me with enough clarity to know my next steps on integrating\nit with Hammerspoon. I found a few resources online demonstrating how to extend the\n",{"type":21,"tag":109,"props":110,"children":112},"code",{"className":111},[],[113],{"type":26,"value":114},"package.path",{"type":26,"value":116}," and ",{"type":21,"tag":109,"props":118,"children":120},{"className":119},[],[121],{"type":26,"value":122},"package.cpath",{"type":26,"value":124}," properties in Lua, but I was unable to get this to\nwork.",{"type":21,"tag":126,"props":127,"children":128},"ul",{},[129,139,148],{"type":21,"tag":130,"props":131,"children":132},"li",{},[133],{"type":21,"tag":39,"props":134,"children":137},{"href":135,"rel":136},"https://blog.exupero.org/hammerspoon-with-fennel/",[43],[138],{"type":26,"value":135},{"type":21,"tag":130,"props":140,"children":141},{},[142],{"type":21,"tag":39,"props":143,"children":146},{"href":144,"rel":145},"https://github.com/Hammerspoon/hammerspoon/issues/2377#issuecomment-636331435",[43],[147],{"type":26,"value":144},{"type":21,"tag":130,"props":149,"children":150},{},[151],{"type":21,"tag":39,"props":152,"children":155},{"href":153,"rel":154},"https://github.com/agzam/spacehammer/blob/master/init.lua",[43],[156],{"type":26,"value":153},{"type":21,"tag":22,"props":158,"children":159},{},[160,162,168],{"type":26,"value":161},"Ultimately, I opted to include the ",{"type":21,"tag":109,"props":163,"children":165},{"className":164},[],[166],{"type":26,"value":167},"fennel.lua",{"type":26,"value":169}," file to my Hammerspoon configuration,\nand while not ideal, it does make the configuration nicely self-contained. I'll leave it\nas a future task to include the module installed with LuaRocks.",{"type":21,"tag":22,"props":171,"children":172},{},[173,175,181,183,189,191,197],{"type":26,"value":174},"With Fennel now included in my Hammerspoon configuration, all I need to do is configure\nthe ",{"type":21,"tag":109,"props":176,"children":178},{"className":177},[],[179],{"type":26,"value":180},"fennel.path",{"type":26,"value":182}," to point to the ",{"type":21,"tag":109,"props":184,"children":186},{"className":185},[],[187],{"type":26,"value":188},"*.fnl",{"type":26,"value":190}," files in the ",{"type":21,"tag":109,"props":192,"children":194},{"className":193},[],[195],{"type":26,"value":196},".hammerspoon/",{"type":26,"value":198}," directory, and\nttranslating these modules can begin!",{"type":21,"tag":200,"props":201,"children":205},"pre",{"className":202,"code":203,"language":204,"meta":7,"style":7},"language-lua shiki shiki-themes github-light","-- init.lua\n\nlocal fennel = require('fennel')\n\nfennel.path = package.path .. \";\" .. os.getenv(\"HOME\") .. \"/.hammerspoon/?.fnl\"\n\ntable.insert(package.loaders or package.searchers, fennel.searcher)\n\nrequire 'main'\n","lua",[206],{"type":21,"tag":109,"props":207,"children":208},{"__ignoreMap":7},[209,221,231,274,282,350,358,400,408],{"type":21,"tag":210,"props":211,"children":214},"span",{"class":212,"line":213},"line",1,[215],{"type":21,"tag":210,"props":216,"children":218},{"style":217},"--shiki-default:#6A737D",[219],{"type":26,"value":220},"-- init.lua\n",{"type":21,"tag":210,"props":222,"children":224},{"class":212,"line":223},2,[225],{"type":21,"tag":210,"props":226,"children":228},{"emptyLinePlaceholder":227},true,[229],{"type":26,"value":230},"\n",{"type":21,"tag":210,"props":232,"children":234},{"class":212,"line":233},3,[235,241,247,252,258,263,269],{"type":21,"tag":210,"props":236,"children":238},{"style":237},"--shiki-default:#D73A49",[239],{"type":26,"value":240},"local",{"type":21,"tag":210,"props":242,"children":244},{"style":243},"--shiki-default:#24292E",[245],{"type":26,"value":246}," fennel ",{"type":21,"tag":210,"props":248,"children":249},{"style":237},[250],{"type":26,"value":251},"=",{"type":21,"tag":210,"props":253,"children":255},{"style":254},"--shiki-default:#005CC5",[256],{"type":26,"value":257}," require",{"type":21,"tag":210,"props":259,"children":260},{"style":243},[261],{"type":26,"value":262},"(",{"type":21,"tag":210,"props":264,"children":266},{"style":265},"--shiki-default:#032F62",[267],{"type":26,"value":268},"'fennel'",{"type":21,"tag":210,"props":270,"children":271},{"style":243},[272],{"type":26,"value":273},")\n",{"type":21,"tag":210,"props":275,"children":277},{"class":212,"line":276},4,[278],{"type":21,"tag":210,"props":279,"children":280},{"emptyLinePlaceholder":227},[281],{"type":26,"value":230},{"type":21,"tag":210,"props":283,"children":285},{"class":212,"line":284},5,[286,291,297,302,307,312,317,322,327,331,336,341,345],{"type":21,"tag":210,"props":287,"children":288},{"style":243},[289],{"type":26,"value":290},"fennel.",{"type":21,"tag":210,"props":292,"children":294},{"style":293},"--shiki-default:#6F42C1",[295],{"type":26,"value":296},"path",{"type":21,"tag":210,"props":298,"children":299},{"style":237},[300],{"type":26,"value":301}," =",{"type":21,"tag":210,"props":303,"children":304},{"style":254},[305],{"type":26,"value":306}," package.path",{"type":21,"tag":210,"props":308,"children":309},{"style":237},[310],{"type":26,"value":311}," ..",{"type":21,"tag":210,"props":313,"children":314},{"style":265},[315],{"type":26,"value":316}," \";\" ",{"type":21,"tag":210,"props":318,"children":319},{"style":237},[320],{"type":26,"value":321},"..",{"type":21,"tag":210,"props":323,"children":324},{"style":254},[325],{"type":26,"value":326}," os.getenv",{"type":21,"tag":210,"props":328,"children":329},{"style":243},[330],{"type":26,"value":262},{"type":21,"tag":210,"props":332,"children":333},{"style":265},[334],{"type":26,"value":335},"\"HOME\"",{"type":21,"tag":210,"props":337,"children":338},{"style":243},[339],{"type":26,"value":340},") ",{"type":21,"tag":210,"props":342,"children":343},{"style":237},[344],{"type":26,"value":321},{"type":21,"tag":210,"props":346,"children":347},{"style":265},[348],{"type":26,"value":349}," \"/.hammerspoon/?.fnl\"\n",{"type":21,"tag":210,"props":351,"children":353},{"class":212,"line":352},6,[354],{"type":21,"tag":210,"props":355,"children":356},{"emptyLinePlaceholder":227},[357],{"type":26,"value":230},{"type":21,"tag":210,"props":359,"children":361},{"class":212,"line":360},7,[362,367,371,376,381,386,391,396],{"type":21,"tag":210,"props":363,"children":364},{"style":254},[365],{"type":26,"value":366},"table.insert",{"type":21,"tag":210,"props":368,"children":369},{"style":243},[370],{"type":26,"value":262},{"type":21,"tag":210,"props":372,"children":373},{"style":254},[374],{"type":26,"value":375},"package.loaders",{"type":21,"tag":210,"props":377,"children":378},{"style":237},[379],{"type":26,"value":380}," or",{"type":21,"tag":210,"props":382,"children":383},{"style":254},[384],{"type":26,"value":385}," package.searchers",{"type":21,"tag":210,"props":387,"children":388},{"style":243},[389],{"type":26,"value":390},", fennel.",{"type":21,"tag":210,"props":392,"children":393},{"style":293},[394],{"type":26,"value":395},"searcher",{"type":21,"tag":210,"props":397,"children":398},{"style":243},[399],{"type":26,"value":273},{"type":21,"tag":210,"props":401,"children":403},{"class":212,"line":402},8,[404],{"type":21,"tag":210,"props":405,"children":406},{"emptyLinePlaceholder":227},[407],{"type":26,"value":230},{"type":21,"tag":210,"props":409,"children":411},{"class":212,"line":410},9,[412,417],{"type":21,"tag":210,"props":413,"children":414},{"style":254},[415],{"type":26,"value":416},"require",{"type":21,"tag":210,"props":418,"children":419},{"style":265},[420],{"type":26,"value":421}," 'main'\n",{"type":21,"tag":68,"props":423,"children":425},{"id":424},"translating-lua-to-fennel",[426],{"type":26,"value":427},"Translating Lua to Fennel",{"type":21,"tag":22,"props":429,"children":430},{},[431,433,440,442,448,450,456],{"type":26,"value":432},"As a Fennel novice, I was happy to see that the Fennel project provides an online\ncross-compiler for Lua and Fennel called ",{"type":21,"tag":39,"props":434,"children":437},{"href":435,"rel":436},"https://fennel-lang.org/see",[43],[438],{"type":26,"value":439},"anti-fennel",{"type":26,"value":441},", and while it can generate some\nstrange-looking Fennel code, it was an extremely useful tool for me to get\nup-and-running right away. For example, by pasting the simple ",{"type":21,"tag":109,"props":443,"children":445},{"className":444},[],[446],{"type":26,"value":447},"sleep",{"type":26,"value":449}," function\nfrom the ",{"type":21,"tag":109,"props":451,"children":453},{"className":452},[],[454],{"type":26,"value":455},"helpers",{"type":26,"value":457}," module into the compiler:",{"type":21,"tag":200,"props":459,"children":461},{"className":202,"code":460,"language":204,"meta":7,"style":7},"function sleep(ms)\n os.execute(\"sleep \" .. tonumber(ms) / 1000)\nend\n",[462],{"type":21,"tag":109,"props":463,"children":464},{"__ignoreMap":7},[465,483,528],{"type":21,"tag":210,"props":466,"children":467},{"class":212,"line":213},[468,473,478],{"type":21,"tag":210,"props":469,"children":470},{"style":237},[471],{"type":26,"value":472},"function",{"type":21,"tag":210,"props":474,"children":475},{"style":293},[476],{"type":26,"value":477}," sleep",{"type":21,"tag":210,"props":479,"children":480},{"style":243},[481],{"type":26,"value":482},"(ms)\n",{"type":21,"tag":210,"props":484,"children":485},{"class":212,"line":223},[486,491,495,500,504,509,514,519,524],{"type":21,"tag":210,"props":487,"children":488},{"style":254},[489],{"type":26,"value":490}," os.execute",{"type":21,"tag":210,"props":492,"children":493},{"style":243},[494],{"type":26,"value":262},{"type":21,"tag":210,"props":496,"children":497},{"style":265},[498],{"type":26,"value":499},"\"sleep \" ",{"type":21,"tag":210,"props":501,"children":502},{"style":237},[503],{"type":26,"value":321},{"type":21,"tag":210,"props":505,"children":506},{"style":254},[507],{"type":26,"value":508}," tonumber",{"type":21,"tag":210,"props":510,"children":511},{"style":243},[512],{"type":26,"value":513},"(ms) ",{"type":21,"tag":210,"props":515,"children":516},{"style":237},[517],{"type":26,"value":518},"/",{"type":21,"tag":210,"props":520,"children":521},{"style":254},[522],{"type":26,"value":523}," 1000",{"type":21,"tag":210,"props":525,"children":526},{"style":243},[527],{"type":26,"value":273},{"type":21,"tag":210,"props":529,"children":530},{"class":212,"line":233},[531],{"type":21,"tag":210,"props":532,"children":533},{"style":237},[534],{"type":26,"value":535},"end\n",{"type":21,"tag":200,"props":537,"children":540},{"className":538,"code":539,"language":12,"meta":7,"style":7},"language-lisp shiki shiki-themes github-light","(fn sleep [ms]\n (os.execute (.. \"sleep \" (/ (tonumber ms) 1000))))\n",[541],{"type":21,"tag":109,"props":542,"children":543},{"__ignoreMap":7},[544,552],{"type":21,"tag":210,"props":545,"children":546},{"class":212,"line":213},[547],{"type":21,"tag":210,"props":548,"children":549},{"style":243},[550],{"type":26,"value":551},"(fn sleep [ms]\n",{"type":21,"tag":210,"props":553,"children":554},{"class":212,"line":223},[555,560,565,570,574,579,584],{"type":21,"tag":210,"props":556,"children":557},{"style":243},[558],{"type":26,"value":559}," (os.execute (.. ",{"type":21,"tag":210,"props":561,"children":562},{"style":265},[563],{"type":26,"value":564},"\"sleep \"",{"type":21,"tag":210,"props":566,"children":567},{"style":243},[568],{"type":26,"value":569}," (",{"type":21,"tag":210,"props":571,"children":572},{"style":237},[573],{"type":26,"value":518},{"type":21,"tag":210,"props":575,"children":576},{"style":243},[577],{"type":26,"value":578}," (tonumber ms) ",{"type":21,"tag":210,"props":580,"children":581},{"style":254},[582],{"type":26,"value":583},"1000",{"type":21,"tag":210,"props":585,"children":586},{"style":243},[587],{"type":26,"value":588},"))))\n",{"type":21,"tag":22,"props":590,"children":591},{},[592,594,600],{"type":26,"value":593},"As another example, here is the output for my ",{"type":21,"tag":595,"props":596,"children":597},"em",{},[598],{"type":26,"value":599},"caffeine",{"type":26,"value":601}," toggle:",{"type":21,"tag":200,"props":603,"children":605},{"className":202,"code":604,"language":204,"meta":7,"style":7},"hs.hotkey.bind(HYPER, \"0\", function()\n hs.caffeinate.toggle(\"displayIdle\")\n if hs.caffeinate.get(\"displayIdle\") then\n helpers:show(\"Caffeine Enabled\", nil, helpers.styles.success, helpers.assets.check)\n else\n helpers:show(\"Caffeine Disabled\", nil, helpers.styles.error, helpers.assets.ban)\n end\nend)\n",[606],{"type":21,"tag":109,"props":607,"children":608},{"__ignoreMap":7},[609,655,690,733,810,818,888,896],{"type":21,"tag":210,"props":610,"children":611},{"class":212,"line":213},[612,617,622,626,631,636,641,646,650],{"type":21,"tag":210,"props":613,"children":614},{"style":243},[615],{"type":26,"value":616},"hs.",{"type":21,"tag":210,"props":618,"children":619},{"style":293},[620],{"type":26,"value":621},"hotkey",{"type":21,"tag":210,"props":623,"children":624},{"style":243},[625],{"type":26,"value":66},{"type":21,"tag":210,"props":627,"children":628},{"style":254},[629],{"type":26,"value":630},"bind",{"type":21,"tag":210,"props":632,"children":633},{"style":243},[634],{"type":26,"value":635},"(HYPER, ",{"type":21,"tag":210,"props":637,"children":638},{"style":265},[639],{"type":26,"value":640},"\"0\"",{"type":21,"tag":210,"props":642,"children":643},{"style":243},[644],{"type":26,"value":645},", ",{"type":21,"tag":210,"props":647,"children":648},{"style":237},[649],{"type":26,"value":472},{"type":21,"tag":210,"props":651,"children":652},{"style":243},[653],{"type":26,"value":654},"()\n",{"type":21,"tag":210,"props":656,"children":657},{"class":212,"line":223},[658,663,668,672,677,681,686],{"type":21,"tag":210,"props":659,"children":660},{"style":243},[661],{"type":26,"value":662}," hs.",{"type":21,"tag":210,"props":664,"children":665},{"style":293},[666],{"type":26,"value":667},"caffeinate",{"type":21,"tag":210,"props":669,"children":670},{"style":243},[671],{"type":26,"value":66},{"type":21,"tag":210,"props":673,"children":674},{"style":254},[675],{"type":26,"value":676},"toggle",{"type":21,"tag":210,"props":678,"children":679},{"style":243},[680],{"type":26,"value":262},{"type":21,"tag":210,"props":682,"children":683},{"style":265},[684],{"type":26,"value":685},"\"displayIdle\"",{"type":21,"tag":210,"props":687,"children":688},{"style":243},[689],{"type":26,"value":273},{"type":21,"tag":210,"props":691,"children":692},{"class":212,"line":233},[693,698,703,707,711,716,720,724,728],{"type":21,"tag":210,"props":694,"children":695},{"style":237},[696],{"type":26,"value":697}," if",{"type":21,"tag":210,"props":699,"children":700},{"style":243},[701],{"type":26,"value":702}," hs.",{"type":21,"tag":210,"props":704,"children":705},{"style":293},[706],{"type":26,"value":667},{"type":21,"tag":210,"props":708,"children":709},{"style":243},[710],{"type":26,"value":66},{"type":21,"tag":210,"props":712,"children":713},{"style":254},[714],{"type":26,"value":715},"get",{"type":21,"tag":210,"props":717,"children":718},{"style":243},[719],{"type":26,"value":262},{"type":21,"tag":210,"props":721,"children":722},{"style":265},[723],{"type":26,"value":685},{"type":21,"tag":210,"props":725,"children":726},{"style":243},[727],{"type":26,"value":340},{"type":21,"tag":210,"props":729,"children":730},{"style":237},[731],{"type":26,"value":732},"then\n",{"type":21,"tag":210,"props":734,"children":735},{"class":212,"line":276},[736,741,746,751,755,760,764,769,774,779,783,788,792,797,801,806],{"type":21,"tag":210,"props":737,"children":738},{"style":293},[739],{"type":26,"value":740}," helpers",{"type":21,"tag":210,"props":742,"children":743},{"style":243},[744],{"type":26,"value":745},":",{"type":21,"tag":210,"props":747,"children":748},{"style":254},[749],{"type":26,"value":750},"show",{"type":21,"tag":210,"props":752,"children":753},{"style":243},[754],{"type":26,"value":262},{"type":21,"tag":210,"props":756,"children":757},{"style":265},[758],{"type":26,"value":759},"\"Caffeine Enabled\"",{"type":21,"tag":210,"props":761,"children":762},{"style":243},[763],{"type":26,"value":645},{"type":21,"tag":210,"props":765,"children":766},{"style":254},[767],{"type":26,"value":768},"nil",{"type":21,"tag":210,"props":770,"children":771},{"style":243},[772],{"type":26,"value":773},", helpers.",{"type":21,"tag":210,"props":775,"children":776},{"style":293},[777],{"type":26,"value":778},"styles",{"type":21,"tag":210,"props":780,"children":781},{"style":243},[782],{"type":26,"value":66},{"type":21,"tag":210,"props":784,"children":785},{"style":293},[786],{"type":26,"value":787},"success",{"type":21,"tag":210,"props":789,"children":790},{"style":243},[791],{"type":26,"value":773},{"type":21,"tag":210,"props":793,"children":794},{"style":293},[795],{"type":26,"value":796},"assets",{"type":21,"tag":210,"props":798,"children":799},{"style":243},[800],{"type":26,"value":66},{"type":21,"tag":210,"props":802,"children":803},{"style":293},[804],{"type":26,"value":805},"check",{"type":21,"tag":210,"props":807,"children":808},{"style":243},[809],{"type":26,"value":273},{"type":21,"tag":210,"props":811,"children":812},{"class":212,"line":284},[813],{"type":21,"tag":210,"props":814,"children":815},{"style":237},[816],{"type":26,"value":817}," else\n",{"type":21,"tag":210,"props":819,"children":820},{"class":212,"line":352},[821,825,829,833,837,842,846,850,854,858,862,867,871,875,879,884],{"type":21,"tag":210,"props":822,"children":823},{"style":293},[824],{"type":26,"value":740},{"type":21,"tag":210,"props":826,"children":827},{"style":243},[828],{"type":26,"value":745},{"type":21,"tag":210,"props":830,"children":831},{"style":254},[832],{"type":26,"value":750},{"type":21,"tag":210,"props":834,"children":835},{"style":243},[836],{"type":26,"value":262},{"type":21,"tag":210,"props":838,"children":839},{"style":265},[840],{"type":26,"value":841},"\"Caffeine Disabled\"",{"type":21,"tag":210,"props":843,"children":844},{"style":243},[845],{"type":26,"value":645},{"type":21,"tag":210,"props":847,"children":848},{"style":254},[849],{"type":26,"value":768},{"type":21,"tag":210,"props":851,"children":852},{"style":243},[853],{"type":26,"value":773},{"type":21,"tag":210,"props":855,"children":856},{"style":293},[857],{"type":26,"value":778},{"type":21,"tag":210,"props":859,"children":860},{"style":243},[861],{"type":26,"value":66},{"type":21,"tag":210,"props":863,"children":864},{"style":293},[865],{"type":26,"value":866},"error",{"type":21,"tag":210,"props":868,"children":869},{"style":243},[870],{"type":26,"value":773},{"type":21,"tag":210,"props":872,"children":873},{"style":293},[874],{"type":26,"value":796},{"type":21,"tag":210,"props":876,"children":877},{"style":243},[878],{"type":26,"value":66},{"type":21,"tag":210,"props":880,"children":881},{"style":293},[882],{"type":26,"value":883},"ban",{"type":21,"tag":210,"props":885,"children":886},{"style":243},[887],{"type":26,"value":273},{"type":21,"tag":210,"props":889,"children":890},{"class":212,"line":360},[891],{"type":21,"tag":210,"props":892,"children":893},{"style":237},[894],{"type":26,"value":895}," end\n",{"type":21,"tag":210,"props":897,"children":898},{"class":212,"line":402},[899,904],{"type":21,"tag":210,"props":900,"children":901},{"style":237},[902],{"type":26,"value":903},"end",{"type":21,"tag":210,"props":905,"children":906},{"style":243},[907],{"type":26,"value":273},{"type":21,"tag":200,"props":909,"children":911},{"className":538,"code":910,"language":12,"meta":7,"style":7},"(hs.hotkey.bind HYPER :0\n (fn [] (hs.caffeinate.toggle :displayIdle)\n (if (hs.caffeinate.get :displayIdle)\n (helpers:show \"Caffeine Enabled\" nil helpers.styles.success helpers.assets.check)\n (helpers:show \"Caffeine Disabled\" nil helpers.styles.error helpers.assets.ban)))) \n",[912],{"type":21,"tag":109,"props":913,"children":914},{"__ignoreMap":7},[915,928,945,971,993],{"type":21,"tag":210,"props":916,"children":917},{"class":212,"line":213},[918,923],{"type":21,"tag":210,"props":919,"children":920},{"style":243},[921],{"type":26,"value":922},"(hs.hotkey.bind HYPER ",{"type":21,"tag":210,"props":924,"children":925},{"style":237},[926],{"type":26,"value":927},":0\n",{"type":21,"tag":210,"props":929,"children":930},{"class":212,"line":223},[931,936,941],{"type":21,"tag":210,"props":932,"children":933},{"style":243},[934],{"type":26,"value":935}," (fn [] (hs.caffeinate.toggle ",{"type":21,"tag":210,"props":937,"children":938},{"style":237},[939],{"type":26,"value":940},":displayIdle",{"type":21,"tag":210,"props":942,"children":943},{"style":243},[944],{"type":26,"value":273},{"type":21,"tag":210,"props":946,"children":947},{"class":212,"line":233},[948,953,958,963,967],{"type":21,"tag":210,"props":949,"children":950},{"style":243},[951],{"type":26,"value":952}," (",{"type":21,"tag":210,"props":954,"children":955},{"style":237},[956],{"type":26,"value":957},"if",{"type":21,"tag":210,"props":959,"children":960},{"style":243},[961],{"type":26,"value":962}," (hs.caffeinate.get ",{"type":21,"tag":210,"props":964,"children":965},{"style":237},[966],{"type":26,"value":940},{"type":21,"tag":210,"props":968,"children":969},{"style":243},[970],{"type":26,"value":273},{"type":21,"tag":210,"props":972,"children":973},{"class":212,"line":276},[974,979,983,988],{"type":21,"tag":210,"props":975,"children":976},{"style":243},[977],{"type":26,"value":978}," (helpers:show ",{"type":21,"tag":210,"props":980,"children":981},{"style":265},[982],{"type":26,"value":759},{"type":21,"tag":210,"props":984,"children":985},{"style":254},[986],{"type":26,"value":987}," nil",{"type":21,"tag":210,"props":989,"children":990},{"style":243},[991],{"type":26,"value":992}," helpers.styles.success helpers.assets.check)\n",{"type":21,"tag":210,"props":994,"children":995},{"class":212,"line":284},[996,1000,1004,1008],{"type":21,"tag":210,"props":997,"children":998},{"style":243},[999],{"type":26,"value":978},{"type":21,"tag":210,"props":1001,"children":1002},{"style":265},[1003],{"type":26,"value":841},{"type":21,"tag":210,"props":1005,"children":1006},{"style":254},[1007],{"type":26,"value":987},{"type":21,"tag":210,"props":1009,"children":1010},{"style":243},[1011],{"type":26,"value":1012}," helpers.styles.error helpers.assets.ban))))\n",{"type":21,"tag":22,"props":1014,"children":1015},{},[1016,1018,1024],{"type":26,"value":1017},"This was especially helpful for more gnarly modules like the ",{"type":21,"tag":109,"props":1019,"children":1021},{"className":1020},[],[1022],{"type":26,"value":1023},"window",{"type":26,"value":1025}," module used for\nwindow management, and seeing the Lua and Fennel code side-by-side was a kick starter in\nlearning the language!",{"type":21,"tag":68,"props":1027,"children":1029},{"id":1028},"next-steps",[1030],{"type":26,"value":1031},"Next Steps",{"type":21,"tag":22,"props":1033,"children":1034},{},[1035],{"type":26,"value":1036},"While my Fennel Hammerspoon configuration now works with parity to its Lua counterpart,\nI have not yet added new features or modules. I look forward to writing new Fennel code,\nand deepen my understanding of Lisp and the Fennel programming language.",{"type":21,"tag":22,"props":1038,"children":1039},{},[1040,1042,1049],{"type":26,"value":1041},"Additionally, before beginning this endeavor, I was already aware of projects like\n",{"type":21,"tag":39,"props":1043,"children":1046},{"href":1044,"rel":1045},"https://github.com/agzam/spacehammer",[43],[1047],{"type":26,"value":1048},"spacehammer",{"type":26,"value":1050},"; a wildly impressive Hammerspoon configuration written in Fennel, but,\nI wanted to start small and learn the integration myself. However, with the basics out\nof the way, I hope to explore this project further, and seek lessons-learned for the\nconfiguration of my own.",{"type":21,"tag":22,"props":1052,"children":1053},{},[1054,1056],{"type":26,"value":1055},"The full pull-request for translating my Lua Hammerspoon configuration to Fennel can be\nfound here: ",{"type":21,"tag":39,"props":1057,"children":1060},{"href":1058,"rel":1059},"https://github.com/cmpadden/dotfiles/pull/19/files",[43],[1061],{"type":26,"value":1058},{"type":21,"tag":1063,"props":1064,"children":1065},"style",{},[1066],{"type":26,"value":1067},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":223,"depth":223,"links":1069},[1070,1071,1072,1073],{"id":70,"depth":223,"text":73},{"id":90,"depth":223,"text":93},{"id":424,"depth":223,"text":427},{"id":1028,"depth":223,"text":1031},"markdown","content:articles:fennel-initial-exploration.md","content","articles/fennel-initial-exploration.md","md",1727638398046] \ No newline at end of file diff --git a/articles/fennel-initial-exploration/index.html b/articles/fennel-initial-exploration/index.html index d5ba21be..d11c1480 100644 --- a/articles/fennel-initial-exploration/index.html +++ b/articles/fennel-initial-exploration/index.html @@ -4,36 +4,35 @@ - - + + - - - - + + + + - - + - - - - - - - - - - - - - - - - -

            Impressions of Fennel with Hammerspoon

            A while back I read an introductory book on Lisp programming titled, "The Little + + + + + + + + + + + + + + + + +

            Impressions of Fennel with Hammerspoon

            A while back I read an introductory book on Lisp programming titled, "The Little Schemer". This book opened my mind to new (to me) programming paradigms, and left me with a strong desire to find a way to incorporate Lisp programming into my every day life. It took some time, but I believe I've found what I've been looking for: Fennel.

            The Fennel programming language is a dialect of Lisp that boasts compatibility with @@ -67,8 +66,8 @@ from the helpers module into the compiler:

            function sleep(ms)
                 os.execute("sleep " .. tonumber(ms) / 1000)
             end
            -
            (fn sleep [ms]
            -  (os.execute (.. "sleep " (/ (tonumber ms) 1000))))
            +
            (fn sleep [ms]
            +  (os.execute (.. "sleep " (/ (tonumber ms) 1000))))
             

            As another example, here is the output for my caffeine toggle:

            hs.hotkey.bind(HYPER, "0", function()
               hs.caffeinate.toggle("displayIdle")
               if hs.caffeinate.get("displayIdle") then
            @@ -77,11 +76,11 @@
                 helpers:show("Caffeine Disabled", nil, helpers.styles.error, helpers.assets.ban)
               end
             end)
            -
            (hs.hotkey.bind HYPER :0
            -  (fn [] (hs.caffeinate.toggle :displayIdle)
            -    (if (hs.caffeinate.get :displayIdle)
            -      (helpers:show "Caffeine Enabled" nil helpers.styles.success helpers.assets.check)
            -      (helpers:show "Caffeine Disabled" nil helpers.styles.error helpers.assets.ban))))
            +
            (hs.hotkey.bind HYPER :0
            +  (fn [] (hs.caffeinate.toggle :displayIdle)
            +    (if (hs.caffeinate.get :displayIdle)
            +      (helpers:show "Caffeine Enabled" nil helpers.styles.success helpers.assets.check)
            +      (helpers:show "Caffeine Disabled" nil helpers.styles.error helpers.assets.ban))))
             

            This was especially helpful for more gnarly modules like the window module used for window management, and seeing the Lua and Fennel code side-by-side was a kick starter in learning the language!

            Next Steps

            While my Fennel Hammerspoon configuration now works with parity to its Lua counterpart, @@ -91,5 +90,5 @@ I wanted to start small and learn the integration myself. However, with the basics out of the way, I hope to explore this project further, and seek lessons-learned for the configuration of my own.

            The full pull-request for translating my Lua Hammerspoon configuration to Fennel can be -found here: https://github.com/cmpadden/dotfiles/pull/19/files

            - \ No newline at end of file +found here: https://github.com/cmpadden/dotfiles/pull/19/files

            + \ No newline at end of file diff --git a/articles/index.html b/articles/index.html index 477cdd7b..ffc76031 100644 --- a/articles/index.html +++ b/articles/index.html @@ -4,27 +4,26 @@ - - - - - - + + + + + + - - + - - - - - - - - - - -

            Blog

            2024-06-09
            Configuring a YubiKey for use with OpenSSH

            YubiKey's are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the "new" ed25519-sk key type that supports FIDO compliant hardware keys.

            2024-05-11
            Using pinentry-mac to sign commits from vim-fugitive

            In order to sign git commits from within Vim using a plugin like tpope/vim-fugitive, it is necessary to configure the gpg-agent to use a GUI based pinentry-program.

            2024-01-08
            Easily Transcribe Podcasts with Whisper.cpp

            If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive whisper.cpp project. This high-performance fork of OpenAI's Whisper can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the Alter Everything podcast.

            2024-01-06
            How To Add an RSS Feed to a Nuxt Website

            If you are a user of Nuxt Content and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application.

            2023-10-22
            Impressions of Fennel with Hammerspoon

            A while back I read an introductory book on Lisp programming titled, "The Little + + + + + + + + + + +

            Blog

            2024-06-09
            Configuring a YubiKey for use with OpenSSH

            YubiKey's are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the "new" ed25519-sk key type that supports FIDO compliant hardware keys.

            2024-05-11
            Using pinentry-mac to sign commits from vim-fugitive

            In order to sign git commits from within Vim using a plugin like tpope/vim-fugitive, it is necessary to configure the gpg-agent to use a GUI based pinentry-program.

            2024-01-08
            Easily Transcribe Podcasts with Whisper.cpp

            If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive whisper.cpp project. This high-performance fork of OpenAI's Whisper can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the Alter Everything podcast.

            2024-01-06
            How To Add an RSS Feed to a Nuxt Website

            If you are a user of Nuxt Content and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application.

            2023-10-22
            Impressions of Fennel with Hammerspoon

            A while back I read an introductory book on Lisp programming titled, "The Little Schemer". This book opened my mind to new (to me) programming paradigms, and left me with a strong desire to find a way to incorporate Lisp programming into my every day life. It took some time, but I believe I've found what I've been looking for: Fennel.

            2023-01-01
            Exploring the Digital Ocean `doctl` Utility

            I recently had the need to spool up a small ephemeral Linux instance, and wanted to try something new by exploring the Digital Ocean doctl command line utility. @@ -45,5 +44,5 @@ few years, and have recently decided to dust it off.

            Since the last time the device has been powered on, there have been many great improvements to the firmware, and it was very-much due for an upgrade. The following steps outline how the firmware was upgraded on the APU from the -already-installed operating system -- CentOS.

            Categories

            embedded
            homelab
            linux
            lisp
            programming
            python
            tips
            tooling
            web

            Tags

            apu
            archlinux
            bash
            configurations
            digital-ocean
            docker
            fennel
            hammerspoon
            homelab
            linux
            lisp
            micropython
            ml
            mocks
            nuxt
            pcengine
            rss
            selinux
            supermicro
            testing
            tip
            truenas
            tutorial
            unix
            vagrant
            vim
            whisper.cpp
            - \ No newline at end of file +already-installed operating system -- CentOS.

            Categories

            embedded
            homelab
            linux
            lisp
            programming
            python
            tips
            tooling
            web

            Tags

            apu
            archlinux
            bash
            configurations
            digital-ocean
            docker
            fennel
            hammerspoon
            homelab
            linux
            lisp
            micropython
            ml
            mocks
            nuxt
            pcengine
            rss
            selinux
            supermicro
            testing
            tip
            truenas
            tutorial
            unix
            vagrant
            vim
            whisper.cpp
            + \ No newline at end of file diff --git a/articles/migrate-truenas-from-core-to-scale/_payload.json b/articles/migrate-truenas-from-core-to-scale/_payload.json index 5472630d..130c0899 100644 --- a/articles/migrate-truenas-from-core-to-scale/_payload.json +++ b/articles/migrate-truenas-from-core-to-scale/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":205},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"tags":11,"categories":15,"excerpt":16,"body":26,"_type":199,"_id":200,"_source":201,"_file":202,"_stem":203,"_extension":204},"/articles/migrate-truenas-from-core-to-scale","articles",false,"","Migrate to TrueNAS Scale from TrueNAS Core","TrueNAS Scale offers a variety of interesting features that are not supported in its TrueNAS Core counterpart. Most notably, because the base operating system is Debian Linux, opposed to FreeBSD, there is native support for Linux containers via Docker, and Kubernetes Pods! This post walks through the steps required to upgrade from TrueNAS Core to TrueNAS Scale.","2021-12-28",[12,13,14],"homelab","supermicro","truenas",[12],{"type":17,"children":18},"root",[19],{"type":20,"tag":21,"props":22,"children":23},"element","p",{},[24],{"type":25,"value":9},"text",{"type":17,"children":27,"toc":196},[28,32,45,175,180],{"type":20,"tag":21,"props":29,"children":30},{},[31],{"type":25,"value":9},{"type":20,"tag":21,"props":33,"children":34},{},[35,37,43],{"type":25,"value":36},"Thankfully, the upgrade procedure to migrate from TrueNAS Core to TrueNAS Scale is relatively straight forward. All it requires is to create a bootable USB of the TrueNAS Scale image, boot the USB, and select ",{"type":20,"tag":38,"props":39,"children":40},"em",{},[41],{"type":25,"value":42},"Install/Upgrade",{"type":25,"value":44}," in the installation wizard. But for the sake of being thorough, you can find instructions on how to backup system configurations and install the OS below.",{"type":20,"tag":46,"props":47,"children":48},"ol",{},[49,96,125,130,154,159],{"type":20,"tag":50,"props":51,"children":52},"li",{},[53,55],{"type":25,"value":54},"Make a backup of your system’s configuration\n",{"type":20,"tag":46,"props":56,"children":57},{},[58,70],{"type":20,"tag":50,"props":59,"children":60},{},[61,63],{"type":25,"value":62},"Navigate to ",{"type":20,"tag":64,"props":65,"children":67},"code",{"className":66},[],[68],{"type":25,"value":69},"System > General",{"type":20,"tag":50,"props":71,"children":72},{},[73,75,81,83,88,90],{"type":25,"value":74},"Click ",{"type":20,"tag":64,"props":76,"children":78},{"className":77},[],[79],{"type":25,"value":80},"Save Config",{"type":25,"value":82},", check the ",{"type":20,"tag":38,"props":84,"children":85},{},[86],{"type":25,"value":87},"Export Secret Seed",{"type":25,"value":89}," box, and click ",{"type":20,"tag":64,"props":91,"children":93},{"className":92},[],[94],{"type":25,"value":95},"Save",{"type":20,"tag":50,"props":97,"children":98},{},[99,101],{"type":25,"value":100},"Export dataset keys for the encrypted pools\n",{"type":20,"tag":46,"props":102,"children":103},{},[104,114],{"type":20,"tag":50,"props":105,"children":106},{},[107,108],{"type":25,"value":62},{"type":20,"tag":64,"props":109,"children":111},{"className":110},[],[112],{"type":25,"value":113},"Storage > Pools",{"type":20,"tag":50,"props":115,"children":116},{},[117,119],{"type":25,"value":118},"Click the cog icon, and select ",{"type":20,"tag":64,"props":120,"children":122},{"className":121},[],[123],{"type":25,"value":124},"Export Dataset Keys",{"type":20,"tag":50,"props":126,"children":127},{},[128],{"type":25,"value":129},"Insert the TrueNAS Core bootable USB into the NAS",{"type":20,"tag":50,"props":131,"children":132},{},[133,135,140,142,147,149],{"type":25,"value":134},"From the Supermicro IPMI interface select ",{"type":20,"tag":38,"props":136,"children":137},{},[138],{"type":25,"value":139},"Remote Control",{"type":25,"value":141}," and ",{"type":20,"tag":38,"props":143,"children":144},{},[145],{"type":25,"value":146},"iKVM/HTML5",{"type":25,"value":148}," and select ",{"type":20,"tag":38,"props":150,"children":151},{},[152],{"type":25,"value":153},"Reboot",{"type":20,"tag":50,"props":155,"children":156},{},[157],{"type":25,"value":158},"Select the bootable USB as the boot device",{"type":20,"tag":50,"props":160,"children":161},{},[162,164,168,170],{"type":25,"value":163},"From the TrueNAS installation wizard, select ",{"type":20,"tag":38,"props":165,"children":166},{},[167],{"type":25,"value":42},{"type":25,"value":169},", select the drive that contains the TrueNAS installation, and select ",{"type":20,"tag":38,"props":171,"children":172},{},[173],{"type":25,"value":174},"Upgrade Install",{"type":20,"tag":21,"props":176,"children":177},{},[178],{"type":25,"value":179},"Reboot the device, and voila — you should be up-and-running! Give the system a quick rundown to validate that your settings and pools have transferred correctly, and then enjoy all the container goodness!",{"type":20,"tag":21,"props":181,"children":182},{},[183,185,194],{"type":25,"value":184},"For a breakdown of the differences between TrueNAS Core, Enterprise, and Scale, you can reference ",{"type":20,"tag":186,"props":187,"children":191},"a",{"href":188,"rel":189},"https://www.truenas.com/help-me-choose/",[190],"nofollow",[192],{"type":25,"value":193},"this table",{"type":25,"value":195},".",{"title":7,"searchDepth":197,"depth":197,"links":198},2,[],"markdown","content:articles:migrate-truenas-from-core-to-scale.md","content","articles/migrate-truenas-from-core-to-scale.md","articles/migrate-truenas-from-core-to-scale","md",1726174739517] \ No newline at end of file +[{"data":1,"prerenderedAt":204},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"tags":11,"categories":15,"excerpt":16,"body":26,"_type":199,"_id":200,"_source":201,"_file":202,"_extension":203},"/articles/migrate-truenas-from-core-to-scale","articles",false,"","Migrate to TrueNAS Scale from TrueNAS Core","TrueNAS Scale offers a variety of interesting features that are not supported in its TrueNAS Core counterpart. Most notably, because the base operating system is Debian Linux, opposed to FreeBSD, there is native support for Linux containers via Docker, and Kubernetes Pods! This post walks through the steps required to upgrade from TrueNAS Core to TrueNAS Scale.","2021-12-28",[12,13,14],"homelab","supermicro","truenas",[12],{"type":17,"children":18},"root",[19],{"type":20,"tag":21,"props":22,"children":23},"element","p",{},[24],{"type":25,"value":9},"text",{"type":17,"children":27,"toc":196},[28,32,45,175,180],{"type":20,"tag":21,"props":29,"children":30},{},[31],{"type":25,"value":9},{"type":20,"tag":21,"props":33,"children":34},{},[35,37,43],{"type":25,"value":36},"Thankfully, the upgrade procedure to migrate from TrueNAS Core to TrueNAS Scale is relatively straight forward. All it requires is to create a bootable USB of the TrueNAS Scale image, boot the USB, and select ",{"type":20,"tag":38,"props":39,"children":40},"em",{},[41],{"type":25,"value":42},"Install/Upgrade",{"type":25,"value":44}," in the installation wizard. But for the sake of being thorough, you can find instructions on how to backup system configurations and install the OS below.",{"type":20,"tag":46,"props":47,"children":48},"ol",{},[49,96,125,130,154,159],{"type":20,"tag":50,"props":51,"children":52},"li",{},[53,55],{"type":25,"value":54},"Make a backup of your system’s configuration\n",{"type":20,"tag":46,"props":56,"children":57},{},[58,70],{"type":20,"tag":50,"props":59,"children":60},{},[61,63],{"type":25,"value":62},"Navigate to ",{"type":20,"tag":64,"props":65,"children":67},"code",{"className":66},[],[68],{"type":25,"value":69},"System > General",{"type":20,"tag":50,"props":71,"children":72},{},[73,75,81,83,88,90],{"type":25,"value":74},"Click ",{"type":20,"tag":64,"props":76,"children":78},{"className":77},[],[79],{"type":25,"value":80},"Save Config",{"type":25,"value":82},", check the ",{"type":20,"tag":38,"props":84,"children":85},{},[86],{"type":25,"value":87},"Export Secret Seed",{"type":25,"value":89}," box, and click ",{"type":20,"tag":64,"props":91,"children":93},{"className":92},[],[94],{"type":25,"value":95},"Save",{"type":20,"tag":50,"props":97,"children":98},{},[99,101],{"type":25,"value":100},"Export dataset keys for the encrypted pools\n",{"type":20,"tag":46,"props":102,"children":103},{},[104,114],{"type":20,"tag":50,"props":105,"children":106},{},[107,108],{"type":25,"value":62},{"type":20,"tag":64,"props":109,"children":111},{"className":110},[],[112],{"type":25,"value":113},"Storage > Pools",{"type":20,"tag":50,"props":115,"children":116},{},[117,119],{"type":25,"value":118},"Click the cog icon, and select ",{"type":20,"tag":64,"props":120,"children":122},{"className":121},[],[123],{"type":25,"value":124},"Export Dataset Keys",{"type":20,"tag":50,"props":126,"children":127},{},[128],{"type":25,"value":129},"Insert the TrueNAS Core bootable USB into the NAS",{"type":20,"tag":50,"props":131,"children":132},{},[133,135,140,142,147,149],{"type":25,"value":134},"From the Supermicro IPMI interface select ",{"type":20,"tag":38,"props":136,"children":137},{},[138],{"type":25,"value":139},"Remote Control",{"type":25,"value":141}," and ",{"type":20,"tag":38,"props":143,"children":144},{},[145],{"type":25,"value":146},"iKVM/HTML5",{"type":25,"value":148}," and select ",{"type":20,"tag":38,"props":150,"children":151},{},[152],{"type":25,"value":153},"Reboot",{"type":20,"tag":50,"props":155,"children":156},{},[157],{"type":25,"value":158},"Select the bootable USB as the boot device",{"type":20,"tag":50,"props":160,"children":161},{},[162,164,168,170],{"type":25,"value":163},"From the TrueNAS installation wizard, select ",{"type":20,"tag":38,"props":165,"children":166},{},[167],{"type":25,"value":42},{"type":25,"value":169},", select the drive that contains the TrueNAS installation, and select ",{"type":20,"tag":38,"props":171,"children":172},{},[173],{"type":25,"value":174},"Upgrade Install",{"type":20,"tag":21,"props":176,"children":177},{},[178],{"type":25,"value":179},"Reboot the device, and voila — you should be up-and-running! Give the system a quick rundown to validate that your settings and pools have transferred correctly, and then enjoy all the container goodness!",{"type":20,"tag":21,"props":181,"children":182},{},[183,185,194],{"type":25,"value":184},"For a breakdown of the differences between TrueNAS Core, Enterprise, and Scale, you can reference ",{"type":20,"tag":186,"props":187,"children":191},"a",{"href":188,"rel":189},"https://www.truenas.com/help-me-choose/",[190],"nofollow",[192],{"type":25,"value":193},"this table",{"type":25,"value":195},".",{"title":7,"searchDepth":197,"depth":197,"links":198},2,[],"markdown","content:articles:migrate-truenas-from-core-to-scale.md","content","articles/migrate-truenas-from-core-to-scale.md","md",1727638398049] \ No newline at end of file diff --git a/articles/migrate-truenas-from-core-to-scale/index.html b/articles/migrate-truenas-from-core-to-scale/index.html index fba701c8..83ee88f7 100644 --- a/articles/migrate-truenas-from-core-to-scale/index.html +++ b/articles/migrate-truenas-from-core-to-scale/index.html @@ -4,30 +4,29 @@ - - + + - - - - + + + + - - + - - - - - - - - - - - - -

            Migrate to TrueNAS Scale from TrueNAS Core

            TrueNAS Scale offers a variety of interesting features that are not supported in its TrueNAS Core counterpart. Most notably, because the base operating system is Debian Linux, opposed to FreeBSD, there is native support for Linux containers via Docker, and Kubernetes Pods! This post walks through the steps required to upgrade from TrueNAS Core to TrueNAS Scale.

            Thankfully, the upgrade procedure to migrate from TrueNAS Core to TrueNAS Scale is relatively straight forward. All it requires is to create a bootable USB of the TrueNAS Scale image, boot the USB, and select Install/Upgrade in the installation wizard. But for the sake of being thorough, you can find instructions on how to backup system configurations and install the OS below.

            1. Make a backup of your system’s configuration + + + + + + + + + + + + +

              Migrate to TrueNAS Scale from TrueNAS Core

              TrueNAS Scale offers a variety of interesting features that are not supported in its TrueNAS Core counterpart. Most notably, because the base operating system is Debian Linux, opposed to FreeBSD, there is native support for Linux containers via Docker, and Kubernetes Pods! This post walks through the steps required to upgrade from TrueNAS Core to TrueNAS Scale.

              Thankfully, the upgrade procedure to migrate from TrueNAS Core to TrueNAS Scale is relatively straight forward. All it requires is to create a bootable USB of the TrueNAS Scale image, boot the USB, and select Install/Upgrade in the installation wizard. But for the sake of being thorough, you can find instructions on how to backup system configurations and install the OS below.

              1. Make a backup of your system’s configuration
                1. Navigate to System > General
                2. Click Save Config, check the Export Secret Seed box, and click Save
              2. Export dataset keys for the encrypted pools -
                1. Navigate to Storage > Pools
                2. Click the cog icon, and select Export Dataset Keys
              3. Insert the TrueNAS Core bootable USB into the NAS
              4. From the Supermicro IPMI interface select Remote Control and iKVM/HTML5 and select Reboot
              5. Select the bootable USB as the boot device
              6. From the TrueNAS installation wizard, select Install/Upgrade, select the drive that contains the TrueNAS installation, and select Upgrade Install

              Reboot the device, and voila — you should be up-and-running! Give the system a quick rundown to validate that your settings and pools have transferred correctly, and then enjoy all the container goodness!

              For a breakdown of the differences between TrueNAS Core, Enterprise, and Scale, you can reference this table.

              - \ No newline at end of file +
              1. Navigate to Storage > Pools
              2. Click the cog icon, and select Export Dataset Keys
            2. Insert the TrueNAS Core bootable USB into the NAS
            3. From the Supermicro IPMI interface select Remote Control and iKVM/HTML5 and select Reboot
            4. Select the bootable USB as the boot device
            5. From the TrueNAS installation wizard, select Install/Upgrade, select the drive that contains the TrueNAS installation, and select Upgrade Install

            Reboot the device, and voila — you should be up-and-running! Give the system a quick rundown to validate that your settings and pools have transferred correctly, and then enjoy all the container goodness!

            For a breakdown of the differences between TrueNAS Core, Enterprise, and Scale, you can reference this table.

            + \ No newline at end of file diff --git a/articles/nuxt-content-rss-feed/_payload.json b/articles/nuxt-content-rss-feed/_payload.json index 6ce02e31..f32dc7ac 100644 --- a/articles/nuxt-content-rss-feed/_payload.json +++ b/articles/nuxt-content-rss-feed/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":1792},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"draft":6,"date":10,"tags":11,"categories":14,"cover_image":16,"excerpt":17,"body":39,"_type":1786,"_id":1787,"_source":1788,"_file":1789,"_stem":1790,"_extension":1791},"/articles/nuxt-content-rss-feed","articles",false,"","How To Add an RSS Feed to a Nuxt Website","If you are a user of Nuxt Content and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application.","2024-01-06",[12,13],"nuxt","rss",[15],"programming","/images/nuxt-content-rss-feed.jpg",{"type":18,"children":19},"root",[20],{"type":21,"tag":22,"props":23,"children":24},"element","p",{},[25,28,37],{"type":26,"value":27},"text","If you are a user of ",{"type":21,"tag":29,"props":30,"children":34},"a",{"href":31,"rel":32},"https://content.nuxt.com/",[33],"nofollow",[35],{"type":26,"value":36},"Nuxt Content",{"type":26,"value":38}," and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application.",{"type":18,"children":40,"toc":1781},[41,51,58,81,87,101,141,162,197,1139,1176,1246,1252,1265,1270,1297,1309,1685,1703,1775],{"type":21,"tag":22,"props":42,"children":43},{},[44,45,50],{"type":26,"value":27},{"type":21,"tag":29,"props":46,"children":48},{"href":31,"rel":47},[33],[49],{"type":26,"value":36},{"type":26,"value":38},{"type":21,"tag":52,"props":53,"children":55},"h2",{"id":54},"preface",[56],{"type":26,"value":57},"Preface",{"type":21,"tag":22,"props":59,"children":60},{},[61,63,70,72,79],{"type":26,"value":62},"In version 2 of Nuxt, the community module, ",{"type":21,"tag":29,"props":64,"children":67},{"href":65,"rel":66},"https://github.com/nuxt-community/feed-module",[33],[68],{"type":26,"value":69},"nuxt-community/feed-module",{"type":26,"value":71}," was a popular choice for adding an RSS feed to your website. However, there has been an unresolved ",{"type":21,"tag":29,"props":73,"children":76},{"href":74,"rel":75},"https://github.com/nuxt-community/feed-module/issues/106",[33],[77],{"type":26,"value":78},"open issue",{"type":26,"value":80}," since April 1st, 2022 to add support for Nuxt v3. Thankfully, implementing this feature without a module is relatively straight forward.",{"type":21,"tag":52,"props":82,"children":84},{"id":83},"instructions",[85],{"type":26,"value":86},"Instructions",{"type":21,"tag":22,"props":88,"children":89},{},[90,92,99],{"type":26,"value":91},"First, install the ",{"type":21,"tag":29,"props":93,"children":96},{"href":94,"rel":95},"https://www.npmjs.com/package/feed",[33],[97],{"type":26,"value":98},"feed",{"type":26,"value":100}," library into your project:",{"type":21,"tag":102,"props":103,"children":107},"pre",{"className":104,"code":105,"language":106,"meta":7,"style":7},"language-shell shiki shiki-themes github-light","npm i -D feed\n","shell",[108],{"type":21,"tag":109,"props":110,"children":111},"code",{"__ignoreMap":7},[112],{"type":21,"tag":113,"props":114,"children":117},"span",{"class":115,"line":116},"line",1,[118,124,130,136],{"type":21,"tag":113,"props":119,"children":121},{"style":120},"--shiki-default:#6F42C1",[122],{"type":26,"value":123},"npm",{"type":21,"tag":113,"props":125,"children":127},{"style":126},"--shiki-default:#032F62",[128],{"type":26,"value":129}," i",{"type":21,"tag":113,"props":131,"children":133},{"style":132},"--shiki-default:#005CC5",[134],{"type":26,"value":135}," -D",{"type":21,"tag":113,"props":137,"children":138},{"style":126},[139],{"type":26,"value":140}," feed\n",{"type":21,"tag":22,"props":142,"children":143},{},[144,146,152,154,160],{"type":26,"value":145},"Then, create a ",{"type":21,"tag":109,"props":147,"children":149},{"className":148},[],[150],{"type":26,"value":151},"server/",{"type":26,"value":153}," folder in your project if it does not already exist, and create a file named ",{"type":21,"tag":109,"props":155,"children":157},{"className":156},[],[158],{"type":26,"value":159},"server/routes/atom.ts",{"type":26,"value":161},".",{"type":21,"tag":22,"props":163,"children":164},{},[165,167,172,174,179,181,187,189,195],{"type":26,"value":166},"Here, we will leverage the ",{"type":21,"tag":109,"props":168,"children":170},{"className":169},[],[171],{"type":26,"value":98},{"type":26,"value":173}," library and construct an XML representation of our Nuxt content. As you can see, we first define our ",{"type":21,"tag":109,"props":175,"children":177},{"className":176},[],[178],{"type":26,"value":98},{"type":26,"value":180}," with metadata associated with our RSS feed. This will be used by RSS readers to provide context to the end user. Then, we query our Nuxt content with ",{"type":21,"tag":109,"props":182,"children":184},{"className":183},[],[185],{"type":26,"value":186},"serverQueryContent",{"type":26,"value":188}," and append a ",{"type":21,"tag":109,"props":190,"children":192},{"className":191},[],[193],{"type":26,"value":194},"feed.addItem",{"type":26,"value":196}," for each article.",{"type":21,"tag":102,"props":198,"children":202},{"className":199,"code":200,"language":201,"meta":7,"style":7},"language-ts shiki shiki-themes github-light","import { serverQueryContent } from '#content/server';\nimport { Feed } from 'feed';\n\nconst BASE_URL = \"https://mywebsite.com\"\nconst AUTHOR_NAME = \"Firstname Lastname\"\n\nexport default defineEventHandler(async (event) => {\n\n const feed = new Feed({\n title: \"My Title\",\n description: \"My Description\",\n id: BASE_URL,\n link: BASE_URL,\n language: \"en\",\n image: `${BASE_URL}/images/placeholder.png`,\n favicon: `${BASE_URL}/favicon.ico`,\n copyright: `All rights reserved ${new Date().getFullYear()}, ${AUTHOR_NAME}`,\n updated: new Date(),\n generator: \"Nuxt static site generation + Feed for Node.js\",\n feedLinks: {\n atom: `${BASE_URL}/atom`\n },\n author: {\n name: AUTHOR_NAME,\n }\n });\n\n const articles = await serverQueryContent(event).find();\n\n articles.forEach((article) => {\n feed.addItem({\n title: article.title ? article.title : \"Missing Title\",\n id: article._path,\n link: `${BASE_URL}${article._path}`,\n description: article.description,\n author: [\n {\n name: AUTHOR_NAME,\n },\n ],\n date: new Date(article.date),\n image: article.cover_image ? `${BASE_URL}/${article.cover_image}` : undefined\n });\n });\n\n return feed.atom1();\n});\n","ts",[203],{"type":21,"tag":109,"props":204,"children":205},{"__ignoreMap":7},[206,236,262,272,296,318,326,381,389,422,441,459,477,494,512,539,565,623,645,663,672,694,703,712,729,738,747,755,797,805,841,859,892,901,944,953,962,971,988,997,1006,1028,1082,1091,1099,1107,1130],{"type":21,"tag":113,"props":207,"children":208},{"class":115,"line":116},[209,215,221,226,231],{"type":21,"tag":113,"props":210,"children":212},{"style":211},"--shiki-default:#D73A49",[213],{"type":26,"value":214},"import",{"type":21,"tag":113,"props":216,"children":218},{"style":217},"--shiki-default:#24292E",[219],{"type":26,"value":220}," { serverQueryContent } ",{"type":21,"tag":113,"props":222,"children":223},{"style":211},[224],{"type":26,"value":225},"from",{"type":21,"tag":113,"props":227,"children":228},{"style":126},[229],{"type":26,"value":230}," '#content/server'",{"type":21,"tag":113,"props":232,"children":233},{"style":217},[234],{"type":26,"value":235},";\n",{"type":21,"tag":113,"props":237,"children":239},{"class":115,"line":238},2,[240,244,249,253,258],{"type":21,"tag":113,"props":241,"children":242},{"style":211},[243],{"type":26,"value":214},{"type":21,"tag":113,"props":245,"children":246},{"style":217},[247],{"type":26,"value":248}," { Feed } ",{"type":21,"tag":113,"props":250,"children":251},{"style":211},[252],{"type":26,"value":225},{"type":21,"tag":113,"props":254,"children":255},{"style":126},[256],{"type":26,"value":257}," 'feed'",{"type":21,"tag":113,"props":259,"children":260},{"style":217},[261],{"type":26,"value":235},{"type":21,"tag":113,"props":263,"children":265},{"class":115,"line":264},3,[266],{"type":21,"tag":113,"props":267,"children":269},{"emptyLinePlaceholder":268},true,[270],{"type":26,"value":271},"\n",{"type":21,"tag":113,"props":273,"children":275},{"class":115,"line":274},4,[276,281,286,291],{"type":21,"tag":113,"props":277,"children":278},{"style":211},[279],{"type":26,"value":280},"const",{"type":21,"tag":113,"props":282,"children":283},{"style":132},[284],{"type":26,"value":285}," BASE_URL",{"type":21,"tag":113,"props":287,"children":288},{"style":211},[289],{"type":26,"value":290}," =",{"type":21,"tag":113,"props":292,"children":293},{"style":126},[294],{"type":26,"value":295}," \"https://mywebsite.com\"\n",{"type":21,"tag":113,"props":297,"children":299},{"class":115,"line":298},5,[300,304,309,313],{"type":21,"tag":113,"props":301,"children":302},{"style":211},[303],{"type":26,"value":280},{"type":21,"tag":113,"props":305,"children":306},{"style":132},[307],{"type":26,"value":308}," AUTHOR_NAME",{"type":21,"tag":113,"props":310,"children":311},{"style":211},[312],{"type":26,"value":290},{"type":21,"tag":113,"props":314,"children":315},{"style":126},[316],{"type":26,"value":317}," \"Firstname Lastname\"\n",{"type":21,"tag":113,"props":319,"children":321},{"class":115,"line":320},6,[322],{"type":21,"tag":113,"props":323,"children":324},{"emptyLinePlaceholder":268},[325],{"type":26,"value":271},{"type":21,"tag":113,"props":327,"children":329},{"class":115,"line":328},7,[330,335,340,345,350,355,360,366,371,376],{"type":21,"tag":113,"props":331,"children":332},{"style":211},[333],{"type":26,"value":334},"export",{"type":21,"tag":113,"props":336,"children":337},{"style":211},[338],{"type":26,"value":339}," default",{"type":21,"tag":113,"props":341,"children":342},{"style":120},[343],{"type":26,"value":344}," defineEventHandler",{"type":21,"tag":113,"props":346,"children":347},{"style":217},[348],{"type":26,"value":349},"(",{"type":21,"tag":113,"props":351,"children":352},{"style":211},[353],{"type":26,"value":354},"async",{"type":21,"tag":113,"props":356,"children":357},{"style":217},[358],{"type":26,"value":359}," (",{"type":21,"tag":113,"props":361,"children":363},{"style":362},"--shiki-default:#E36209",[364],{"type":26,"value":365},"event",{"type":21,"tag":113,"props":367,"children":368},{"style":217},[369],{"type":26,"value":370},") ",{"type":21,"tag":113,"props":372,"children":373},{"style":211},[374],{"type":26,"value":375},"=>",{"type":21,"tag":113,"props":377,"children":378},{"style":217},[379],{"type":26,"value":380}," {\n",{"type":21,"tag":113,"props":382,"children":384},{"class":115,"line":383},8,[385],{"type":21,"tag":113,"props":386,"children":387},{"emptyLinePlaceholder":268},[388],{"type":26,"value":271},{"type":21,"tag":113,"props":390,"children":392},{"class":115,"line":391},9,[393,398,403,407,412,417],{"type":21,"tag":113,"props":394,"children":395},{"style":211},[396],{"type":26,"value":397}," const",{"type":21,"tag":113,"props":399,"children":400},{"style":132},[401],{"type":26,"value":402}," feed",{"type":21,"tag":113,"props":404,"children":405},{"style":211},[406],{"type":26,"value":290},{"type":21,"tag":113,"props":408,"children":409},{"style":211},[410],{"type":26,"value":411}," new",{"type":21,"tag":113,"props":413,"children":414},{"style":120},[415],{"type":26,"value":416}," Feed",{"type":21,"tag":113,"props":418,"children":419},{"style":217},[420],{"type":26,"value":421},"({\n",{"type":21,"tag":113,"props":423,"children":425},{"class":115,"line":424},10,[426,431,436],{"type":21,"tag":113,"props":427,"children":428},{"style":217},[429],{"type":26,"value":430}," title: ",{"type":21,"tag":113,"props":432,"children":433},{"style":126},[434],{"type":26,"value":435},"\"My Title\"",{"type":21,"tag":113,"props":437,"children":438},{"style":217},[439],{"type":26,"value":440},",\n",{"type":21,"tag":113,"props":442,"children":444},{"class":115,"line":443},11,[445,450,455],{"type":21,"tag":113,"props":446,"children":447},{"style":217},[448],{"type":26,"value":449}," description: ",{"type":21,"tag":113,"props":451,"children":452},{"style":126},[453],{"type":26,"value":454},"\"My Description\"",{"type":21,"tag":113,"props":456,"children":457},{"style":217},[458],{"type":26,"value":440},{"type":21,"tag":113,"props":460,"children":462},{"class":115,"line":461},12,[463,468,473],{"type":21,"tag":113,"props":464,"children":465},{"style":217},[466],{"type":26,"value":467}," id: ",{"type":21,"tag":113,"props":469,"children":470},{"style":132},[471],{"type":26,"value":472},"BASE_URL",{"type":21,"tag":113,"props":474,"children":475},{"style":217},[476],{"type":26,"value":440},{"type":21,"tag":113,"props":478,"children":480},{"class":115,"line":479},13,[481,486,490],{"type":21,"tag":113,"props":482,"children":483},{"style":217},[484],{"type":26,"value":485}," link: ",{"type":21,"tag":113,"props":487,"children":488},{"style":132},[489],{"type":26,"value":472},{"type":21,"tag":113,"props":491,"children":492},{"style":217},[493],{"type":26,"value":440},{"type":21,"tag":113,"props":495,"children":497},{"class":115,"line":496},14,[498,503,508],{"type":21,"tag":113,"props":499,"children":500},{"style":217},[501],{"type":26,"value":502}," language: ",{"type":21,"tag":113,"props":504,"children":505},{"style":126},[506],{"type":26,"value":507},"\"en\"",{"type":21,"tag":113,"props":509,"children":510},{"style":217},[511],{"type":26,"value":440},{"type":21,"tag":113,"props":513,"children":515},{"class":115,"line":514},15,[516,521,526,530,535],{"type":21,"tag":113,"props":517,"children":518},{"style":217},[519],{"type":26,"value":520}," image: ",{"type":21,"tag":113,"props":522,"children":523},{"style":126},[524],{"type":26,"value":525},"`${",{"type":21,"tag":113,"props":527,"children":528},{"style":132},[529],{"type":26,"value":472},{"type":21,"tag":113,"props":531,"children":532},{"style":126},[533],{"type":26,"value":534},"}/images/placeholder.png`",{"type":21,"tag":113,"props":536,"children":537},{"style":217},[538],{"type":26,"value":440},{"type":21,"tag":113,"props":540,"children":542},{"class":115,"line":541},16,[543,548,552,556,561],{"type":21,"tag":113,"props":544,"children":545},{"style":217},[546],{"type":26,"value":547}," favicon: ",{"type":21,"tag":113,"props":549,"children":550},{"style":126},[551],{"type":26,"value":525},{"type":21,"tag":113,"props":553,"children":554},{"style":132},[555],{"type":26,"value":472},{"type":21,"tag":113,"props":557,"children":558},{"style":126},[559],{"type":26,"value":560},"}/favicon.ico`",{"type":21,"tag":113,"props":562,"children":563},{"style":217},[564],{"type":26,"value":440},{"type":21,"tag":113,"props":566,"children":568},{"class":115,"line":567},17,[569,574,579,584,589,594,599,604,609,614,619],{"type":21,"tag":113,"props":570,"children":571},{"style":217},[572],{"type":26,"value":573}," copyright: ",{"type":21,"tag":113,"props":575,"children":576},{"style":126},[577],{"type":26,"value":578},"`All rights reserved ${",{"type":21,"tag":113,"props":580,"children":581},{"style":211},[582],{"type":26,"value":583},"new",{"type":21,"tag":113,"props":585,"children":586},{"style":120},[587],{"type":26,"value":588}," Date",{"type":21,"tag":113,"props":590,"children":591},{"style":126},[592],{"type":26,"value":593},"().",{"type":21,"tag":113,"props":595,"children":596},{"style":120},[597],{"type":26,"value":598},"getFullYear",{"type":21,"tag":113,"props":600,"children":601},{"style":126},[602],{"type":26,"value":603},"()",{"type":21,"tag":113,"props":605,"children":606},{"style":126},[607],{"type":26,"value":608},"}, ${",{"type":21,"tag":113,"props":610,"children":611},{"style":132},[612],{"type":26,"value":613},"AUTHOR_NAME",{"type":21,"tag":113,"props":615,"children":616},{"style":126},[617],{"type":26,"value":618},"}`",{"type":21,"tag":113,"props":620,"children":621},{"style":217},[622],{"type":26,"value":440},{"type":21,"tag":113,"props":624,"children":626},{"class":115,"line":625},18,[627,632,636,640],{"type":21,"tag":113,"props":628,"children":629},{"style":217},[630],{"type":26,"value":631}," updated: ",{"type":21,"tag":113,"props":633,"children":634},{"style":211},[635],{"type":26,"value":583},{"type":21,"tag":113,"props":637,"children":638},{"style":120},[639],{"type":26,"value":588},{"type":21,"tag":113,"props":641,"children":642},{"style":217},[643],{"type":26,"value":644},"(),\n",{"type":21,"tag":113,"props":646,"children":648},{"class":115,"line":647},19,[649,654,659],{"type":21,"tag":113,"props":650,"children":651},{"style":217},[652],{"type":26,"value":653}," generator: ",{"type":21,"tag":113,"props":655,"children":656},{"style":126},[657],{"type":26,"value":658},"\"Nuxt static site generation + Feed for Node.js\"",{"type":21,"tag":113,"props":660,"children":661},{"style":217},[662],{"type":26,"value":440},{"type":21,"tag":113,"props":664,"children":666},{"class":115,"line":665},20,[667],{"type":21,"tag":113,"props":668,"children":669},{"style":217},[670],{"type":26,"value":671}," feedLinks: {\n",{"type":21,"tag":113,"props":673,"children":675},{"class":115,"line":674},21,[676,681,685,689],{"type":21,"tag":113,"props":677,"children":678},{"style":217},[679],{"type":26,"value":680}," atom: ",{"type":21,"tag":113,"props":682,"children":683},{"style":126},[684],{"type":26,"value":525},{"type":21,"tag":113,"props":686,"children":687},{"style":132},[688],{"type":26,"value":472},{"type":21,"tag":113,"props":690,"children":691},{"style":126},[692],{"type":26,"value":693},"}/atom`\n",{"type":21,"tag":113,"props":695,"children":697},{"class":115,"line":696},22,[698],{"type":21,"tag":113,"props":699,"children":700},{"style":217},[701],{"type":26,"value":702}," },\n",{"type":21,"tag":113,"props":704,"children":706},{"class":115,"line":705},23,[707],{"type":21,"tag":113,"props":708,"children":709},{"style":217},[710],{"type":26,"value":711}," author: {\n",{"type":21,"tag":113,"props":713,"children":715},{"class":115,"line":714},24,[716,721,725],{"type":21,"tag":113,"props":717,"children":718},{"style":217},[719],{"type":26,"value":720}," name: ",{"type":21,"tag":113,"props":722,"children":723},{"style":132},[724],{"type":26,"value":613},{"type":21,"tag":113,"props":726,"children":727},{"style":217},[728],{"type":26,"value":440},{"type":21,"tag":113,"props":730,"children":732},{"class":115,"line":731},25,[733],{"type":21,"tag":113,"props":734,"children":735},{"style":217},[736],{"type":26,"value":737}," }\n",{"type":21,"tag":113,"props":739,"children":741},{"class":115,"line":740},26,[742],{"type":21,"tag":113,"props":743,"children":744},{"style":217},[745],{"type":26,"value":746}," });\n",{"type":21,"tag":113,"props":748,"children":750},{"class":115,"line":749},27,[751],{"type":21,"tag":113,"props":752,"children":753},{"emptyLinePlaceholder":268},[754],{"type":26,"value":271},{"type":21,"tag":113,"props":756,"children":758},{"class":115,"line":757},28,[759,763,768,772,777,782,787,792],{"type":21,"tag":113,"props":760,"children":761},{"style":211},[762],{"type":26,"value":397},{"type":21,"tag":113,"props":764,"children":765},{"style":132},[766],{"type":26,"value":767}," articles",{"type":21,"tag":113,"props":769,"children":770},{"style":211},[771],{"type":26,"value":290},{"type":21,"tag":113,"props":773,"children":774},{"style":211},[775],{"type":26,"value":776}," await",{"type":21,"tag":113,"props":778,"children":779},{"style":120},[780],{"type":26,"value":781}," serverQueryContent",{"type":21,"tag":113,"props":783,"children":784},{"style":217},[785],{"type":26,"value":786},"(event).",{"type":21,"tag":113,"props":788,"children":789},{"style":120},[790],{"type":26,"value":791},"find",{"type":21,"tag":113,"props":793,"children":794},{"style":217},[795],{"type":26,"value":796},"();\n",{"type":21,"tag":113,"props":798,"children":800},{"class":115,"line":799},29,[801],{"type":21,"tag":113,"props":802,"children":803},{"emptyLinePlaceholder":268},[804],{"type":26,"value":271},{"type":21,"tag":113,"props":806,"children":808},{"class":115,"line":807},30,[809,814,819,824,829,833,837],{"type":21,"tag":113,"props":810,"children":811},{"style":217},[812],{"type":26,"value":813}," articles.",{"type":21,"tag":113,"props":815,"children":816},{"style":120},[817],{"type":26,"value":818},"forEach",{"type":21,"tag":113,"props":820,"children":821},{"style":217},[822],{"type":26,"value":823},"((",{"type":21,"tag":113,"props":825,"children":826},{"style":362},[827],{"type":26,"value":828},"article",{"type":21,"tag":113,"props":830,"children":831},{"style":217},[832],{"type":26,"value":370},{"type":21,"tag":113,"props":834,"children":835},{"style":211},[836],{"type":26,"value":375},{"type":21,"tag":113,"props":838,"children":839},{"style":217},[840],{"type":26,"value":380},{"type":21,"tag":113,"props":842,"children":844},{"class":115,"line":843},31,[845,850,855],{"type":21,"tag":113,"props":846,"children":847},{"style":217},[848],{"type":26,"value":849}," feed.",{"type":21,"tag":113,"props":851,"children":852},{"style":120},[853],{"type":26,"value":854},"addItem",{"type":21,"tag":113,"props":856,"children":857},{"style":217},[858],{"type":26,"value":421},{"type":21,"tag":113,"props":860,"children":862},{"class":115,"line":861},32,[863,868,873,878,883,888],{"type":21,"tag":113,"props":864,"children":865},{"style":217},[866],{"type":26,"value":867}," title: article.title ",{"type":21,"tag":113,"props":869,"children":870},{"style":211},[871],{"type":26,"value":872},"?",{"type":21,"tag":113,"props":874,"children":875},{"style":217},[876],{"type":26,"value":877}," article.title ",{"type":21,"tag":113,"props":879,"children":880},{"style":211},[881],{"type":26,"value":882},":",{"type":21,"tag":113,"props":884,"children":885},{"style":126},[886],{"type":26,"value":887}," \"Missing Title\"",{"type":21,"tag":113,"props":889,"children":890},{"style":217},[891],{"type":26,"value":440},{"type":21,"tag":113,"props":893,"children":895},{"class":115,"line":894},33,[896],{"type":21,"tag":113,"props":897,"children":898},{"style":217},[899],{"type":26,"value":900}," id: article._path,\n",{"type":21,"tag":113,"props":902,"children":904},{"class":115,"line":903},34,[905,910,914,918,923,927,931,936,940],{"type":21,"tag":113,"props":906,"children":907},{"style":217},[908],{"type":26,"value":909}," link: ",{"type":21,"tag":113,"props":911,"children":912},{"style":126},[913],{"type":26,"value":525},{"type":21,"tag":113,"props":915,"children":916},{"style":132},[917],{"type":26,"value":472},{"type":21,"tag":113,"props":919,"children":920},{"style":126},[921],{"type":26,"value":922},"}${",{"type":21,"tag":113,"props":924,"children":925},{"style":217},[926],{"type":26,"value":828},{"type":21,"tag":113,"props":928,"children":929},{"style":126},[930],{"type":26,"value":161},{"type":21,"tag":113,"props":932,"children":933},{"style":217},[934],{"type":26,"value":935},"_path",{"type":21,"tag":113,"props":937,"children":938},{"style":126},[939],{"type":26,"value":618},{"type":21,"tag":113,"props":941,"children":942},{"style":217},[943],{"type":26,"value":440},{"type":21,"tag":113,"props":945,"children":947},{"class":115,"line":946},35,[948],{"type":21,"tag":113,"props":949,"children":950},{"style":217},[951],{"type":26,"value":952}," description: article.description,\n",{"type":21,"tag":113,"props":954,"children":956},{"class":115,"line":955},36,[957],{"type":21,"tag":113,"props":958,"children":959},{"style":217},[960],{"type":26,"value":961}," author: [\n",{"type":21,"tag":113,"props":963,"children":965},{"class":115,"line":964},37,[966],{"type":21,"tag":113,"props":967,"children":968},{"style":217},[969],{"type":26,"value":970}," {\n",{"type":21,"tag":113,"props":972,"children":974},{"class":115,"line":973},38,[975,980,984],{"type":21,"tag":113,"props":976,"children":977},{"style":217},[978],{"type":26,"value":979}," name: ",{"type":21,"tag":113,"props":981,"children":982},{"style":132},[983],{"type":26,"value":613},{"type":21,"tag":113,"props":985,"children":986},{"style":217},[987],{"type":26,"value":440},{"type":21,"tag":113,"props":989,"children":991},{"class":115,"line":990},39,[992],{"type":21,"tag":113,"props":993,"children":994},{"style":217},[995],{"type":26,"value":996}," },\n",{"type":21,"tag":113,"props":998,"children":1000},{"class":115,"line":999},40,[1001],{"type":21,"tag":113,"props":1002,"children":1003},{"style":217},[1004],{"type":26,"value":1005}," ],\n",{"type":21,"tag":113,"props":1007,"children":1009},{"class":115,"line":1008},41,[1010,1015,1019,1023],{"type":21,"tag":113,"props":1011,"children":1012},{"style":217},[1013],{"type":26,"value":1014}," date: ",{"type":21,"tag":113,"props":1016,"children":1017},{"style":211},[1018],{"type":26,"value":583},{"type":21,"tag":113,"props":1020,"children":1021},{"style":120},[1022],{"type":26,"value":588},{"type":21,"tag":113,"props":1024,"children":1025},{"style":217},[1026],{"type":26,"value":1027},"(article.date),\n",{"type":21,"tag":113,"props":1029,"children":1031},{"class":115,"line":1030},42,[1032,1037,1041,1046,1050,1055,1059,1063,1068,1072,1077],{"type":21,"tag":113,"props":1033,"children":1034},{"style":217},[1035],{"type":26,"value":1036}," image: article.cover_image ",{"type":21,"tag":113,"props":1038,"children":1039},{"style":211},[1040],{"type":26,"value":872},{"type":21,"tag":113,"props":1042,"children":1043},{"style":126},[1044],{"type":26,"value":1045}," `${",{"type":21,"tag":113,"props":1047,"children":1048},{"style":132},[1049],{"type":26,"value":472},{"type":21,"tag":113,"props":1051,"children":1052},{"style":126},[1053],{"type":26,"value":1054},"}/${",{"type":21,"tag":113,"props":1056,"children":1057},{"style":217},[1058],{"type":26,"value":828},{"type":21,"tag":113,"props":1060,"children":1061},{"style":126},[1062],{"type":26,"value":161},{"type":21,"tag":113,"props":1064,"children":1065},{"style":217},[1066],{"type":26,"value":1067},"cover_image",{"type":21,"tag":113,"props":1069,"children":1070},{"style":126},[1071],{"type":26,"value":618},{"type":21,"tag":113,"props":1073,"children":1074},{"style":211},[1075],{"type":26,"value":1076}," :",{"type":21,"tag":113,"props":1078,"children":1079},{"style":132},[1080],{"type":26,"value":1081}," undefined\n",{"type":21,"tag":113,"props":1083,"children":1085},{"class":115,"line":1084},43,[1086],{"type":21,"tag":113,"props":1087,"children":1088},{"style":217},[1089],{"type":26,"value":1090}," });\n",{"type":21,"tag":113,"props":1092,"children":1094},{"class":115,"line":1093},44,[1095],{"type":21,"tag":113,"props":1096,"children":1097},{"style":217},[1098],{"type":26,"value":746},{"type":21,"tag":113,"props":1100,"children":1102},{"class":115,"line":1101},45,[1103],{"type":21,"tag":113,"props":1104,"children":1105},{"emptyLinePlaceholder":268},[1106],{"type":26,"value":271},{"type":21,"tag":113,"props":1108,"children":1110},{"class":115,"line":1109},46,[1111,1116,1121,1126],{"type":21,"tag":113,"props":1112,"children":1113},{"style":211},[1114],{"type":26,"value":1115}," return",{"type":21,"tag":113,"props":1117,"children":1118},{"style":217},[1119],{"type":26,"value":1120}," feed.",{"type":21,"tag":113,"props":1122,"children":1123},{"style":120},[1124],{"type":26,"value":1125},"atom1",{"type":21,"tag":113,"props":1127,"children":1128},{"style":217},[1129],{"type":26,"value":796},{"type":21,"tag":113,"props":1131,"children":1133},{"class":115,"line":1132},47,[1134],{"type":21,"tag":113,"props":1135,"children":1136},{"style":217},[1137],{"type":26,"value":1138},"});\n",{"type":21,"tag":22,"props":1140,"children":1141},{},[1142,1144,1150,1152,1158,1160,1166,1168,1174],{"type":26,"value":1143},"And that's just about it! Except, if you are statically generating your website with the ",{"type":21,"tag":109,"props":1145,"children":1147},{"className":1146},[],[1148],{"type":26,"value":1149},"nuxt generate",{"type":26,"value":1151}," command, you will need to configure this server-side route to be pre-rendered on site generation. This is as simple as adding a ",{"type":21,"tag":109,"props":1153,"children":1155},{"className":1154},[],[1156],{"type":26,"value":1157},"nitro",{"type":26,"value":1159}," ",{"type":21,"tag":109,"props":1161,"children":1163},{"className":1162},[],[1164],{"type":26,"value":1165},"prerender",{"type":26,"value":1167}," definition in your ",{"type":21,"tag":109,"props":1169,"children":1171},{"className":1170},[],[1172],{"type":26,"value":1173},"nuxt.config.ts",{"type":26,"value":1175}," file, like so:",{"type":21,"tag":102,"props":1177,"children":1179},{"className":199,"code":1178,"language":201,"meta":7,"style":7},"nitro: {\n prerender: {\n routes: ['/atom']\n }\n}\n",[1180],{"type":21,"tag":109,"props":1181,"children":1182},{"__ignoreMap":7},[1183,1195,1207,1230,1238],{"type":21,"tag":113,"props":1184,"children":1185},{"class":115,"line":116},[1186,1190],{"type":21,"tag":113,"props":1187,"children":1188},{"style":120},[1189],{"type":26,"value":1157},{"type":21,"tag":113,"props":1191,"children":1192},{"style":217},[1193],{"type":26,"value":1194},": {\n",{"type":21,"tag":113,"props":1196,"children":1197},{"class":115,"line":238},[1198,1203],{"type":21,"tag":113,"props":1199,"children":1200},{"style":120},[1201],{"type":26,"value":1202}," prerender",{"type":21,"tag":113,"props":1204,"children":1205},{"style":217},[1206],{"type":26,"value":1194},{"type":21,"tag":113,"props":1208,"children":1209},{"class":115,"line":264},[1210,1215,1220,1225],{"type":21,"tag":113,"props":1211,"children":1212},{"style":120},[1213],{"type":26,"value":1214}," routes",{"type":21,"tag":113,"props":1216,"children":1217},{"style":217},[1218],{"type":26,"value":1219},": [",{"type":21,"tag":113,"props":1221,"children":1222},{"style":126},[1223],{"type":26,"value":1224},"'/atom'",{"type":21,"tag":113,"props":1226,"children":1227},{"style":217},[1228],{"type":26,"value":1229},"]\n",{"type":21,"tag":113,"props":1231,"children":1232},{"class":115,"line":274},[1233],{"type":21,"tag":113,"props":1234,"children":1235},{"style":217},[1236],{"type":26,"value":1237}," }\n",{"type":21,"tag":113,"props":1239,"children":1240},{"class":115,"line":298},[1241],{"type":21,"tag":113,"props":1242,"children":1243},{"style":217},[1244],{"type":26,"value":1245},"}\n",{"type":21,"tag":52,"props":1247,"children":1249},{"id":1248},"bonus",[1250],{"type":26,"value":1251},"Bonus",{"type":21,"tag":22,"props":1253,"children":1254},{},[1255,1257,1263],{"type":26,"value":1256},"You may also be interested in adding a ",{"type":21,"tag":109,"props":1258,"children":1260},{"className":1259},[],[1261],{"type":26,"value":1262},"sitemap.xml",{"type":26,"value":1264}," to your website. This can be done in almost an identical fashion!",{"type":21,"tag":22,"props":1266,"children":1267},{},[1268],{"type":26,"value":1269},"Install the dependency:",{"type":21,"tag":102,"props":1271,"children":1273},{"className":104,"code":1272,"language":106,"meta":7,"style":7},"npm i -D sitemap\n",[1274],{"type":21,"tag":109,"props":1275,"children":1276},{"__ignoreMap":7},[1277],{"type":21,"tag":113,"props":1278,"children":1279},{"class":115,"line":116},[1280,1284,1288,1292],{"type":21,"tag":113,"props":1281,"children":1282},{"style":120},[1283],{"type":26,"value":123},{"type":21,"tag":113,"props":1285,"children":1286},{"style":126},[1287],{"type":26,"value":129},{"type":21,"tag":113,"props":1289,"children":1290},{"style":132},[1291],{"type":26,"value":135},{"type":21,"tag":113,"props":1293,"children":1294},{"style":126},[1295],{"type":26,"value":1296}," sitemap\n",{"type":21,"tag":22,"props":1298,"children":1299},{},[1300,1302,1308],{"type":26,"value":1301},"Create a route at ",{"type":21,"tag":109,"props":1303,"children":1305},{"className":1304},[],[1306],{"type":26,"value":1307},"server/routes/sitemap.xml.ts",{"type":26,"value":882},{"type":21,"tag":102,"props":1310,"children":1312},{"className":199,"code":1311,"language":201,"meta":7,"style":7},"import { serverQueryContent } from '#content/server';\nimport { SitemapStream, streamToPromise } from 'sitemap';\n\nexport default defineEventHandler(async (event) => {\n const articles = await serverQueryContent(event).find();\n\n const sitemap = new SitemapStream({ hostname: 'https://my-website.com/' });\n\n // Add non nuxt content endpoints here\n sitemap.write({ url: '/' });\n sitemap.write({ url: '/articles' });\n\n // Dynamically generate routes for Nuxt markdown content\n articles.forEach((article) => sitemap.write({ url: article._path, changefreq: 'monthly' }));\n sitemap.end();\n\n return (await streamToPromise(sitemap));\n});\n",[1313],{"type":21,"tag":109,"props":1314,"children":1315},{"__ignoreMap":7},[1316,1339,1364,1371,1414,1449,1456,1496,1503,1512,1539,1563,1570,1578,1629,1645,1652,1678],{"type":21,"tag":113,"props":1317,"children":1318},{"class":115,"line":116},[1319,1323,1327,1331,1335],{"type":21,"tag":113,"props":1320,"children":1321},{"style":211},[1322],{"type":26,"value":214},{"type":21,"tag":113,"props":1324,"children":1325},{"style":217},[1326],{"type":26,"value":220},{"type":21,"tag":113,"props":1328,"children":1329},{"style":211},[1330],{"type":26,"value":225},{"type":21,"tag":113,"props":1332,"children":1333},{"style":126},[1334],{"type":26,"value":230},{"type":21,"tag":113,"props":1336,"children":1337},{"style":217},[1338],{"type":26,"value":235},{"type":21,"tag":113,"props":1340,"children":1341},{"class":115,"line":238},[1342,1346,1351,1355,1360],{"type":21,"tag":113,"props":1343,"children":1344},{"style":211},[1345],{"type":26,"value":214},{"type":21,"tag":113,"props":1347,"children":1348},{"style":217},[1349],{"type":26,"value":1350}," { SitemapStream, streamToPromise } ",{"type":21,"tag":113,"props":1352,"children":1353},{"style":211},[1354],{"type":26,"value":225},{"type":21,"tag":113,"props":1356,"children":1357},{"style":126},[1358],{"type":26,"value":1359}," 'sitemap'",{"type":21,"tag":113,"props":1361,"children":1362},{"style":217},[1363],{"type":26,"value":235},{"type":21,"tag":113,"props":1365,"children":1366},{"class":115,"line":264},[1367],{"type":21,"tag":113,"props":1368,"children":1369},{"emptyLinePlaceholder":268},[1370],{"type":26,"value":271},{"type":21,"tag":113,"props":1372,"children":1373},{"class":115,"line":274},[1374,1378,1382,1386,1390,1394,1398,1402,1406,1410],{"type":21,"tag":113,"props":1375,"children":1376},{"style":211},[1377],{"type":26,"value":334},{"type":21,"tag":113,"props":1379,"children":1380},{"style":211},[1381],{"type":26,"value":339},{"type":21,"tag":113,"props":1383,"children":1384},{"style":120},[1385],{"type":26,"value":344},{"type":21,"tag":113,"props":1387,"children":1388},{"style":217},[1389],{"type":26,"value":349},{"type":21,"tag":113,"props":1391,"children":1392},{"style":211},[1393],{"type":26,"value":354},{"type":21,"tag":113,"props":1395,"children":1396},{"style":217},[1397],{"type":26,"value":359},{"type":21,"tag":113,"props":1399,"children":1400},{"style":362},[1401],{"type":26,"value":365},{"type":21,"tag":113,"props":1403,"children":1404},{"style":217},[1405],{"type":26,"value":370},{"type":21,"tag":113,"props":1407,"children":1408},{"style":211},[1409],{"type":26,"value":375},{"type":21,"tag":113,"props":1411,"children":1412},{"style":217},[1413],{"type":26,"value":380},{"type":21,"tag":113,"props":1415,"children":1416},{"class":115,"line":298},[1417,1421,1425,1429,1433,1437,1441,1445],{"type":21,"tag":113,"props":1418,"children":1419},{"style":211},[1420],{"type":26,"value":397},{"type":21,"tag":113,"props":1422,"children":1423},{"style":132},[1424],{"type":26,"value":767},{"type":21,"tag":113,"props":1426,"children":1427},{"style":211},[1428],{"type":26,"value":290},{"type":21,"tag":113,"props":1430,"children":1431},{"style":211},[1432],{"type":26,"value":776},{"type":21,"tag":113,"props":1434,"children":1435},{"style":120},[1436],{"type":26,"value":781},{"type":21,"tag":113,"props":1438,"children":1439},{"style":217},[1440],{"type":26,"value":786},{"type":21,"tag":113,"props":1442,"children":1443},{"style":120},[1444],{"type":26,"value":791},{"type":21,"tag":113,"props":1446,"children":1447},{"style":217},[1448],{"type":26,"value":796},{"type":21,"tag":113,"props":1450,"children":1451},{"class":115,"line":320},[1452],{"type":21,"tag":113,"props":1453,"children":1454},{"emptyLinePlaceholder":268},[1455],{"type":26,"value":271},{"type":21,"tag":113,"props":1457,"children":1458},{"class":115,"line":328},[1459,1463,1468,1472,1476,1481,1486,1491],{"type":21,"tag":113,"props":1460,"children":1461},{"style":211},[1462],{"type":26,"value":397},{"type":21,"tag":113,"props":1464,"children":1465},{"style":132},[1466],{"type":26,"value":1467}," sitemap",{"type":21,"tag":113,"props":1469,"children":1470},{"style":211},[1471],{"type":26,"value":290},{"type":21,"tag":113,"props":1473,"children":1474},{"style":211},[1475],{"type":26,"value":411},{"type":21,"tag":113,"props":1477,"children":1478},{"style":120},[1479],{"type":26,"value":1480}," SitemapStream",{"type":21,"tag":113,"props":1482,"children":1483},{"style":217},[1484],{"type":26,"value":1485},"({ hostname: ",{"type":21,"tag":113,"props":1487,"children":1488},{"style":126},[1489],{"type":26,"value":1490},"'https://my-website.com/'",{"type":21,"tag":113,"props":1492,"children":1493},{"style":217},[1494],{"type":26,"value":1495}," });\n",{"type":21,"tag":113,"props":1497,"children":1498},{"class":115,"line":383},[1499],{"type":21,"tag":113,"props":1500,"children":1501},{"emptyLinePlaceholder":268},[1502],{"type":26,"value":271},{"type":21,"tag":113,"props":1504,"children":1505},{"class":115,"line":391},[1506],{"type":21,"tag":113,"props":1507,"children":1509},{"style":1508},"--shiki-default:#6A737D",[1510],{"type":26,"value":1511}," // Add non nuxt content endpoints here\n",{"type":21,"tag":113,"props":1513,"children":1514},{"class":115,"line":424},[1515,1520,1525,1530,1535],{"type":21,"tag":113,"props":1516,"children":1517},{"style":217},[1518],{"type":26,"value":1519}," sitemap.",{"type":21,"tag":113,"props":1521,"children":1522},{"style":120},[1523],{"type":26,"value":1524},"write",{"type":21,"tag":113,"props":1526,"children":1527},{"style":217},[1528],{"type":26,"value":1529},"({ url: ",{"type":21,"tag":113,"props":1531,"children":1532},{"style":126},[1533],{"type":26,"value":1534},"'/'",{"type":21,"tag":113,"props":1536,"children":1537},{"style":217},[1538],{"type":26,"value":1495},{"type":21,"tag":113,"props":1540,"children":1541},{"class":115,"line":443},[1542,1546,1550,1554,1559],{"type":21,"tag":113,"props":1543,"children":1544},{"style":217},[1545],{"type":26,"value":1519},{"type":21,"tag":113,"props":1547,"children":1548},{"style":120},[1549],{"type":26,"value":1524},{"type":21,"tag":113,"props":1551,"children":1552},{"style":217},[1553],{"type":26,"value":1529},{"type":21,"tag":113,"props":1555,"children":1556},{"style":126},[1557],{"type":26,"value":1558},"'/articles'",{"type":21,"tag":113,"props":1560,"children":1561},{"style":217},[1562],{"type":26,"value":1495},{"type":21,"tag":113,"props":1564,"children":1565},{"class":115,"line":461},[1566],{"type":21,"tag":113,"props":1567,"children":1568},{"emptyLinePlaceholder":268},[1569],{"type":26,"value":271},{"type":21,"tag":113,"props":1571,"children":1572},{"class":115,"line":479},[1573],{"type":21,"tag":113,"props":1574,"children":1575},{"style":1508},[1576],{"type":26,"value":1577}," // Dynamically generate routes for Nuxt markdown content\n",{"type":21,"tag":113,"props":1579,"children":1580},{"class":115,"line":496},[1581,1585,1589,1593,1597,1601,1605,1610,1614,1619,1624],{"type":21,"tag":113,"props":1582,"children":1583},{"style":217},[1584],{"type":26,"value":813},{"type":21,"tag":113,"props":1586,"children":1587},{"style":120},[1588],{"type":26,"value":818},{"type":21,"tag":113,"props":1590,"children":1591},{"style":217},[1592],{"type":26,"value":823},{"type":21,"tag":113,"props":1594,"children":1595},{"style":362},[1596],{"type":26,"value":828},{"type":21,"tag":113,"props":1598,"children":1599},{"style":217},[1600],{"type":26,"value":370},{"type":21,"tag":113,"props":1602,"children":1603},{"style":211},[1604],{"type":26,"value":375},{"type":21,"tag":113,"props":1606,"children":1607},{"style":217},[1608],{"type":26,"value":1609}," sitemap.",{"type":21,"tag":113,"props":1611,"children":1612},{"style":120},[1613],{"type":26,"value":1524},{"type":21,"tag":113,"props":1615,"children":1616},{"style":217},[1617],{"type":26,"value":1618},"({ url: article._path, changefreq: ",{"type":21,"tag":113,"props":1620,"children":1621},{"style":126},[1622],{"type":26,"value":1623},"'monthly'",{"type":21,"tag":113,"props":1625,"children":1626},{"style":217},[1627],{"type":26,"value":1628}," }));\n",{"type":21,"tag":113,"props":1630,"children":1631},{"class":115,"line":514},[1632,1636,1641],{"type":21,"tag":113,"props":1633,"children":1634},{"style":217},[1635],{"type":26,"value":1519},{"type":21,"tag":113,"props":1637,"children":1638},{"style":120},[1639],{"type":26,"value":1640},"end",{"type":21,"tag":113,"props":1642,"children":1643},{"style":217},[1644],{"type":26,"value":796},{"type":21,"tag":113,"props":1646,"children":1647},{"class":115,"line":541},[1648],{"type":21,"tag":113,"props":1649,"children":1650},{"emptyLinePlaceholder":268},[1651],{"type":26,"value":271},{"type":21,"tag":113,"props":1653,"children":1654},{"class":115,"line":567},[1655,1659,1663,1668,1673],{"type":21,"tag":113,"props":1656,"children":1657},{"style":211},[1658],{"type":26,"value":1115},{"type":21,"tag":113,"props":1660,"children":1661},{"style":217},[1662],{"type":26,"value":359},{"type":21,"tag":113,"props":1664,"children":1665},{"style":211},[1666],{"type":26,"value":1667},"await",{"type":21,"tag":113,"props":1669,"children":1670},{"style":120},[1671],{"type":26,"value":1672}," streamToPromise",{"type":21,"tag":113,"props":1674,"children":1675},{"style":217},[1676],{"type":26,"value":1677},"(sitemap));\n",{"type":21,"tag":113,"props":1679,"children":1680},{"class":115,"line":625},[1681],{"type":21,"tag":113,"props":1682,"children":1683},{"style":217},[1684],{"type":26,"value":1138},{"type":21,"tag":22,"props":1686,"children":1687},{},[1688,1690,1695,1697,1702],{"type":26,"value":1689},"And add the ",{"type":21,"tag":109,"props":1691,"children":1693},{"className":1692},[],[1694],{"type":26,"value":1165},{"type":26,"value":1696}," entry in your ",{"type":21,"tag":109,"props":1698,"children":1700},{"className":1699},[],[1701],{"type":26,"value":1173},{"type":26,"value":882},{"type":21,"tag":102,"props":1704,"children":1706},{"className":199,"code":1705,"language":201,"meta":7,"style":7},"nitro: {\n prerender: {\n routes: ['/sitemap.xml', '/atom']\n }\n}\n",[1707],{"type":21,"tag":109,"props":1708,"children":1709},{"__ignoreMap":7},[1710,1721,1732,1761,1768],{"type":21,"tag":113,"props":1711,"children":1712},{"class":115,"line":116},[1713,1717],{"type":21,"tag":113,"props":1714,"children":1715},{"style":120},[1716],{"type":26,"value":1157},{"type":21,"tag":113,"props":1718,"children":1719},{"style":217},[1720],{"type":26,"value":1194},{"type":21,"tag":113,"props":1722,"children":1723},{"class":115,"line":238},[1724,1728],{"type":21,"tag":113,"props":1725,"children":1726},{"style":120},[1727],{"type":26,"value":1202},{"type":21,"tag":113,"props":1729,"children":1730},{"style":217},[1731],{"type":26,"value":1194},{"type":21,"tag":113,"props":1733,"children":1734},{"class":115,"line":264},[1735,1739,1743,1748,1753,1757],{"type":21,"tag":113,"props":1736,"children":1737},{"style":120},[1738],{"type":26,"value":1214},{"type":21,"tag":113,"props":1740,"children":1741},{"style":217},[1742],{"type":26,"value":1219},{"type":21,"tag":113,"props":1744,"children":1745},{"style":126},[1746],{"type":26,"value":1747},"'/sitemap.xml'",{"type":21,"tag":113,"props":1749,"children":1750},{"style":217},[1751],{"type":26,"value":1752},", ",{"type":21,"tag":113,"props":1754,"children":1755},{"style":126},[1756],{"type":26,"value":1224},{"type":21,"tag":113,"props":1758,"children":1759},{"style":217},[1760],{"type":26,"value":1229},{"type":21,"tag":113,"props":1762,"children":1763},{"class":115,"line":274},[1764],{"type":21,"tag":113,"props":1765,"children":1766},{"style":217},[1767],{"type":26,"value":1237},{"type":21,"tag":113,"props":1769,"children":1770},{"class":115,"line":298},[1771],{"type":21,"tag":113,"props":1772,"children":1773},{"style":217},[1774],{"type":26,"value":1245},{"type":21,"tag":1776,"props":1777,"children":1778},"style",{},[1779],{"type":26,"value":1780},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":238,"depth":238,"links":1782},[1783,1784,1785],{"id":54,"depth":238,"text":57},{"id":83,"depth":238,"text":86},{"id":1248,"depth":238,"text":1251},"markdown","content:articles:nuxt-content-rss-feed.md","content","articles/nuxt-content-rss-feed.md","articles/nuxt-content-rss-feed","md",1726174739473] \ No newline at end of file +[{"data":1,"prerenderedAt":1791},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"draft":6,"date":10,"tags":11,"categories":14,"cover_image":16,"excerpt":17,"body":39,"_type":1786,"_id":1787,"_source":1788,"_file":1789,"_extension":1790},"/articles/nuxt-content-rss-feed","articles",false,"","How To Add an RSS Feed to a Nuxt Website","If you are a user of Nuxt Content and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application.","2024-01-06",[12,13],"nuxt","rss",[15],"programming","/images/nuxt-content-rss-feed.jpg",{"type":18,"children":19},"root",[20],{"type":21,"tag":22,"props":23,"children":24},"element","p",{},[25,28,37],{"type":26,"value":27},"text","If you are a user of ",{"type":21,"tag":29,"props":30,"children":34},"a",{"href":31,"rel":32},"https://content.nuxt.com/",[33],"nofollow",[35],{"type":26,"value":36},"Nuxt Content",{"type":26,"value":38}," and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application.",{"type":18,"children":40,"toc":1781},[41,51,58,81,87,101,141,162,197,1139,1176,1246,1252,1265,1270,1297,1309,1685,1703,1775],{"type":21,"tag":22,"props":42,"children":43},{},[44,45,50],{"type":26,"value":27},{"type":21,"tag":29,"props":46,"children":48},{"href":31,"rel":47},[33],[49],{"type":26,"value":36},{"type":26,"value":38},{"type":21,"tag":52,"props":53,"children":55},"h2",{"id":54},"preface",[56],{"type":26,"value":57},"Preface",{"type":21,"tag":22,"props":59,"children":60},{},[61,63,70,72,79],{"type":26,"value":62},"In version 2 of Nuxt, the community module, ",{"type":21,"tag":29,"props":64,"children":67},{"href":65,"rel":66},"https://github.com/nuxt-community/feed-module",[33],[68],{"type":26,"value":69},"nuxt-community/feed-module",{"type":26,"value":71}," was a popular choice for adding an RSS feed to your website. However, there has been an unresolved ",{"type":21,"tag":29,"props":73,"children":76},{"href":74,"rel":75},"https://github.com/nuxt-community/feed-module/issues/106",[33],[77],{"type":26,"value":78},"open issue",{"type":26,"value":80}," since April 1st, 2022 to add support for Nuxt v3. Thankfully, implementing this feature without a module is relatively straight forward.",{"type":21,"tag":52,"props":82,"children":84},{"id":83},"instructions",[85],{"type":26,"value":86},"Instructions",{"type":21,"tag":22,"props":88,"children":89},{},[90,92,99],{"type":26,"value":91},"First, install the ",{"type":21,"tag":29,"props":93,"children":96},{"href":94,"rel":95},"https://www.npmjs.com/package/feed",[33],[97],{"type":26,"value":98},"feed",{"type":26,"value":100}," library into your project:",{"type":21,"tag":102,"props":103,"children":107},"pre",{"className":104,"code":105,"language":106,"meta":7,"style":7},"language-shell shiki shiki-themes github-light","npm i -D feed\n","shell",[108],{"type":21,"tag":109,"props":110,"children":111},"code",{"__ignoreMap":7},[112],{"type":21,"tag":113,"props":114,"children":117},"span",{"class":115,"line":116},"line",1,[118,124,130,136],{"type":21,"tag":113,"props":119,"children":121},{"style":120},"--shiki-default:#6F42C1",[122],{"type":26,"value":123},"npm",{"type":21,"tag":113,"props":125,"children":127},{"style":126},"--shiki-default:#032F62",[128],{"type":26,"value":129}," i",{"type":21,"tag":113,"props":131,"children":133},{"style":132},"--shiki-default:#005CC5",[134],{"type":26,"value":135}," -D",{"type":21,"tag":113,"props":137,"children":138},{"style":126},[139],{"type":26,"value":140}," feed\n",{"type":21,"tag":22,"props":142,"children":143},{},[144,146,152,154,160],{"type":26,"value":145},"Then, create a ",{"type":21,"tag":109,"props":147,"children":149},{"className":148},[],[150],{"type":26,"value":151},"server/",{"type":26,"value":153}," folder in your project if it does not already exist, and create a file named ",{"type":21,"tag":109,"props":155,"children":157},{"className":156},[],[158],{"type":26,"value":159},"server/routes/atom.ts",{"type":26,"value":161},".",{"type":21,"tag":22,"props":163,"children":164},{},[165,167,172,174,179,181,187,189,195],{"type":26,"value":166},"Here, we will leverage the ",{"type":21,"tag":109,"props":168,"children":170},{"className":169},[],[171],{"type":26,"value":98},{"type":26,"value":173}," library and construct an XML representation of our Nuxt content. As you can see, we first define our ",{"type":21,"tag":109,"props":175,"children":177},{"className":176},[],[178],{"type":26,"value":98},{"type":26,"value":180}," with metadata associated with our RSS feed. This will be used by RSS readers to provide context to the end user. Then, we query our Nuxt content with ",{"type":21,"tag":109,"props":182,"children":184},{"className":183},[],[185],{"type":26,"value":186},"serverQueryContent",{"type":26,"value":188}," and append a ",{"type":21,"tag":109,"props":190,"children":192},{"className":191},[],[193],{"type":26,"value":194},"feed.addItem",{"type":26,"value":196}," for each article.",{"type":21,"tag":102,"props":198,"children":202},{"className":199,"code":200,"language":201,"meta":7,"style":7},"language-ts shiki shiki-themes github-light","import { serverQueryContent } from '#content/server';\nimport { Feed } from 'feed';\n\nconst BASE_URL = \"https://mywebsite.com\"\nconst AUTHOR_NAME = \"Firstname Lastname\"\n\nexport default defineEventHandler(async (event) => {\n\n const feed = new Feed({\n title: \"My Title\",\n description: \"My Description\",\n id: BASE_URL,\n link: BASE_URL,\n language: \"en\",\n image: `${BASE_URL}/images/placeholder.png`,\n favicon: `${BASE_URL}/favicon.ico`,\n copyright: `All rights reserved ${new Date().getFullYear()}, ${AUTHOR_NAME}`,\n updated: new Date(),\n generator: \"Nuxt static site generation + Feed for Node.js\",\n feedLinks: {\n atom: `${BASE_URL}/atom`\n },\n author: {\n name: AUTHOR_NAME,\n }\n });\n\n const articles = await serverQueryContent(event).find();\n\n articles.forEach((article) => {\n feed.addItem({\n title: article.title ? article.title : \"Missing Title\",\n id: article._path,\n link: `${BASE_URL}${article._path}`,\n description: article.description,\n author: [\n {\n name: AUTHOR_NAME,\n },\n ],\n date: new Date(article.date),\n image: article.cover_image ? `${BASE_URL}/${article.cover_image}` : undefined\n });\n });\n\n return feed.atom1();\n});\n","ts",[203],{"type":21,"tag":109,"props":204,"children":205},{"__ignoreMap":7},[206,236,262,272,296,318,326,381,389,422,441,459,477,494,512,539,565,623,645,663,672,694,703,712,729,738,747,755,797,805,841,859,892,901,944,953,962,971,988,997,1006,1028,1082,1091,1099,1107,1130],{"type":21,"tag":113,"props":207,"children":208},{"class":115,"line":116},[209,215,221,226,231],{"type":21,"tag":113,"props":210,"children":212},{"style":211},"--shiki-default:#D73A49",[213],{"type":26,"value":214},"import",{"type":21,"tag":113,"props":216,"children":218},{"style":217},"--shiki-default:#24292E",[219],{"type":26,"value":220}," { serverQueryContent } ",{"type":21,"tag":113,"props":222,"children":223},{"style":211},[224],{"type":26,"value":225},"from",{"type":21,"tag":113,"props":227,"children":228},{"style":126},[229],{"type":26,"value":230}," '#content/server'",{"type":21,"tag":113,"props":232,"children":233},{"style":217},[234],{"type":26,"value":235},";\n",{"type":21,"tag":113,"props":237,"children":239},{"class":115,"line":238},2,[240,244,249,253,258],{"type":21,"tag":113,"props":241,"children":242},{"style":211},[243],{"type":26,"value":214},{"type":21,"tag":113,"props":245,"children":246},{"style":217},[247],{"type":26,"value":248}," { Feed } ",{"type":21,"tag":113,"props":250,"children":251},{"style":211},[252],{"type":26,"value":225},{"type":21,"tag":113,"props":254,"children":255},{"style":126},[256],{"type":26,"value":257}," 'feed'",{"type":21,"tag":113,"props":259,"children":260},{"style":217},[261],{"type":26,"value":235},{"type":21,"tag":113,"props":263,"children":265},{"class":115,"line":264},3,[266],{"type":21,"tag":113,"props":267,"children":269},{"emptyLinePlaceholder":268},true,[270],{"type":26,"value":271},"\n",{"type":21,"tag":113,"props":273,"children":275},{"class":115,"line":274},4,[276,281,286,291],{"type":21,"tag":113,"props":277,"children":278},{"style":211},[279],{"type":26,"value":280},"const",{"type":21,"tag":113,"props":282,"children":283},{"style":132},[284],{"type":26,"value":285}," BASE_URL",{"type":21,"tag":113,"props":287,"children":288},{"style":211},[289],{"type":26,"value":290}," =",{"type":21,"tag":113,"props":292,"children":293},{"style":126},[294],{"type":26,"value":295}," \"https://mywebsite.com\"\n",{"type":21,"tag":113,"props":297,"children":299},{"class":115,"line":298},5,[300,304,309,313],{"type":21,"tag":113,"props":301,"children":302},{"style":211},[303],{"type":26,"value":280},{"type":21,"tag":113,"props":305,"children":306},{"style":132},[307],{"type":26,"value":308}," AUTHOR_NAME",{"type":21,"tag":113,"props":310,"children":311},{"style":211},[312],{"type":26,"value":290},{"type":21,"tag":113,"props":314,"children":315},{"style":126},[316],{"type":26,"value":317}," \"Firstname Lastname\"\n",{"type":21,"tag":113,"props":319,"children":321},{"class":115,"line":320},6,[322],{"type":21,"tag":113,"props":323,"children":324},{"emptyLinePlaceholder":268},[325],{"type":26,"value":271},{"type":21,"tag":113,"props":327,"children":329},{"class":115,"line":328},7,[330,335,340,345,350,355,360,366,371,376],{"type":21,"tag":113,"props":331,"children":332},{"style":211},[333],{"type":26,"value":334},"export",{"type":21,"tag":113,"props":336,"children":337},{"style":211},[338],{"type":26,"value":339}," default",{"type":21,"tag":113,"props":341,"children":342},{"style":120},[343],{"type":26,"value":344}," defineEventHandler",{"type":21,"tag":113,"props":346,"children":347},{"style":217},[348],{"type":26,"value":349},"(",{"type":21,"tag":113,"props":351,"children":352},{"style":211},[353],{"type":26,"value":354},"async",{"type":21,"tag":113,"props":356,"children":357},{"style":217},[358],{"type":26,"value":359}," (",{"type":21,"tag":113,"props":361,"children":363},{"style":362},"--shiki-default:#E36209",[364],{"type":26,"value":365},"event",{"type":21,"tag":113,"props":367,"children":368},{"style":217},[369],{"type":26,"value":370},") ",{"type":21,"tag":113,"props":372,"children":373},{"style":211},[374],{"type":26,"value":375},"=>",{"type":21,"tag":113,"props":377,"children":378},{"style":217},[379],{"type":26,"value":380}," {\n",{"type":21,"tag":113,"props":382,"children":384},{"class":115,"line":383},8,[385],{"type":21,"tag":113,"props":386,"children":387},{"emptyLinePlaceholder":268},[388],{"type":26,"value":271},{"type":21,"tag":113,"props":390,"children":392},{"class":115,"line":391},9,[393,398,403,407,412,417],{"type":21,"tag":113,"props":394,"children":395},{"style":211},[396],{"type":26,"value":397}," const",{"type":21,"tag":113,"props":399,"children":400},{"style":132},[401],{"type":26,"value":402}," feed",{"type":21,"tag":113,"props":404,"children":405},{"style":211},[406],{"type":26,"value":290},{"type":21,"tag":113,"props":408,"children":409},{"style":211},[410],{"type":26,"value":411}," new",{"type":21,"tag":113,"props":413,"children":414},{"style":120},[415],{"type":26,"value":416}," Feed",{"type":21,"tag":113,"props":418,"children":419},{"style":217},[420],{"type":26,"value":421},"({\n",{"type":21,"tag":113,"props":423,"children":425},{"class":115,"line":424},10,[426,431,436],{"type":21,"tag":113,"props":427,"children":428},{"style":217},[429],{"type":26,"value":430}," title: ",{"type":21,"tag":113,"props":432,"children":433},{"style":126},[434],{"type":26,"value":435},"\"My Title\"",{"type":21,"tag":113,"props":437,"children":438},{"style":217},[439],{"type":26,"value":440},",\n",{"type":21,"tag":113,"props":442,"children":444},{"class":115,"line":443},11,[445,450,455],{"type":21,"tag":113,"props":446,"children":447},{"style":217},[448],{"type":26,"value":449}," description: ",{"type":21,"tag":113,"props":451,"children":452},{"style":126},[453],{"type":26,"value":454},"\"My Description\"",{"type":21,"tag":113,"props":456,"children":457},{"style":217},[458],{"type":26,"value":440},{"type":21,"tag":113,"props":460,"children":462},{"class":115,"line":461},12,[463,468,473],{"type":21,"tag":113,"props":464,"children":465},{"style":217},[466],{"type":26,"value":467}," id: ",{"type":21,"tag":113,"props":469,"children":470},{"style":132},[471],{"type":26,"value":472},"BASE_URL",{"type":21,"tag":113,"props":474,"children":475},{"style":217},[476],{"type":26,"value":440},{"type":21,"tag":113,"props":478,"children":480},{"class":115,"line":479},13,[481,486,490],{"type":21,"tag":113,"props":482,"children":483},{"style":217},[484],{"type":26,"value":485}," link: ",{"type":21,"tag":113,"props":487,"children":488},{"style":132},[489],{"type":26,"value":472},{"type":21,"tag":113,"props":491,"children":492},{"style":217},[493],{"type":26,"value":440},{"type":21,"tag":113,"props":495,"children":497},{"class":115,"line":496},14,[498,503,508],{"type":21,"tag":113,"props":499,"children":500},{"style":217},[501],{"type":26,"value":502}," language: ",{"type":21,"tag":113,"props":504,"children":505},{"style":126},[506],{"type":26,"value":507},"\"en\"",{"type":21,"tag":113,"props":509,"children":510},{"style":217},[511],{"type":26,"value":440},{"type":21,"tag":113,"props":513,"children":515},{"class":115,"line":514},15,[516,521,526,530,535],{"type":21,"tag":113,"props":517,"children":518},{"style":217},[519],{"type":26,"value":520}," image: ",{"type":21,"tag":113,"props":522,"children":523},{"style":126},[524],{"type":26,"value":525},"`${",{"type":21,"tag":113,"props":527,"children":528},{"style":132},[529],{"type":26,"value":472},{"type":21,"tag":113,"props":531,"children":532},{"style":126},[533],{"type":26,"value":534},"}/images/placeholder.png`",{"type":21,"tag":113,"props":536,"children":537},{"style":217},[538],{"type":26,"value":440},{"type":21,"tag":113,"props":540,"children":542},{"class":115,"line":541},16,[543,548,552,556,561],{"type":21,"tag":113,"props":544,"children":545},{"style":217},[546],{"type":26,"value":547}," favicon: ",{"type":21,"tag":113,"props":549,"children":550},{"style":126},[551],{"type":26,"value":525},{"type":21,"tag":113,"props":553,"children":554},{"style":132},[555],{"type":26,"value":472},{"type":21,"tag":113,"props":557,"children":558},{"style":126},[559],{"type":26,"value":560},"}/favicon.ico`",{"type":21,"tag":113,"props":562,"children":563},{"style":217},[564],{"type":26,"value":440},{"type":21,"tag":113,"props":566,"children":568},{"class":115,"line":567},17,[569,574,579,584,589,594,599,604,609,614,619],{"type":21,"tag":113,"props":570,"children":571},{"style":217},[572],{"type":26,"value":573}," copyright: ",{"type":21,"tag":113,"props":575,"children":576},{"style":126},[577],{"type":26,"value":578},"`All rights reserved ${",{"type":21,"tag":113,"props":580,"children":581},{"style":211},[582],{"type":26,"value":583},"new",{"type":21,"tag":113,"props":585,"children":586},{"style":120},[587],{"type":26,"value":588}," Date",{"type":21,"tag":113,"props":590,"children":591},{"style":126},[592],{"type":26,"value":593},"().",{"type":21,"tag":113,"props":595,"children":596},{"style":120},[597],{"type":26,"value":598},"getFullYear",{"type":21,"tag":113,"props":600,"children":601},{"style":126},[602],{"type":26,"value":603},"()",{"type":21,"tag":113,"props":605,"children":606},{"style":126},[607],{"type":26,"value":608},"}, ${",{"type":21,"tag":113,"props":610,"children":611},{"style":132},[612],{"type":26,"value":613},"AUTHOR_NAME",{"type":21,"tag":113,"props":615,"children":616},{"style":126},[617],{"type":26,"value":618},"}`",{"type":21,"tag":113,"props":620,"children":621},{"style":217},[622],{"type":26,"value":440},{"type":21,"tag":113,"props":624,"children":626},{"class":115,"line":625},18,[627,632,636,640],{"type":21,"tag":113,"props":628,"children":629},{"style":217},[630],{"type":26,"value":631}," updated: ",{"type":21,"tag":113,"props":633,"children":634},{"style":211},[635],{"type":26,"value":583},{"type":21,"tag":113,"props":637,"children":638},{"style":120},[639],{"type":26,"value":588},{"type":21,"tag":113,"props":641,"children":642},{"style":217},[643],{"type":26,"value":644},"(),\n",{"type":21,"tag":113,"props":646,"children":648},{"class":115,"line":647},19,[649,654,659],{"type":21,"tag":113,"props":650,"children":651},{"style":217},[652],{"type":26,"value":653}," generator: ",{"type":21,"tag":113,"props":655,"children":656},{"style":126},[657],{"type":26,"value":658},"\"Nuxt static site generation + Feed for Node.js\"",{"type":21,"tag":113,"props":660,"children":661},{"style":217},[662],{"type":26,"value":440},{"type":21,"tag":113,"props":664,"children":666},{"class":115,"line":665},20,[667],{"type":21,"tag":113,"props":668,"children":669},{"style":217},[670],{"type":26,"value":671}," feedLinks: {\n",{"type":21,"tag":113,"props":673,"children":675},{"class":115,"line":674},21,[676,681,685,689],{"type":21,"tag":113,"props":677,"children":678},{"style":217},[679],{"type":26,"value":680}," atom: ",{"type":21,"tag":113,"props":682,"children":683},{"style":126},[684],{"type":26,"value":525},{"type":21,"tag":113,"props":686,"children":687},{"style":132},[688],{"type":26,"value":472},{"type":21,"tag":113,"props":690,"children":691},{"style":126},[692],{"type":26,"value":693},"}/atom`\n",{"type":21,"tag":113,"props":695,"children":697},{"class":115,"line":696},22,[698],{"type":21,"tag":113,"props":699,"children":700},{"style":217},[701],{"type":26,"value":702}," },\n",{"type":21,"tag":113,"props":704,"children":706},{"class":115,"line":705},23,[707],{"type":21,"tag":113,"props":708,"children":709},{"style":217},[710],{"type":26,"value":711}," author: {\n",{"type":21,"tag":113,"props":713,"children":715},{"class":115,"line":714},24,[716,721,725],{"type":21,"tag":113,"props":717,"children":718},{"style":217},[719],{"type":26,"value":720}," name: ",{"type":21,"tag":113,"props":722,"children":723},{"style":132},[724],{"type":26,"value":613},{"type":21,"tag":113,"props":726,"children":727},{"style":217},[728],{"type":26,"value":440},{"type":21,"tag":113,"props":730,"children":732},{"class":115,"line":731},25,[733],{"type":21,"tag":113,"props":734,"children":735},{"style":217},[736],{"type":26,"value":737}," }\n",{"type":21,"tag":113,"props":739,"children":741},{"class":115,"line":740},26,[742],{"type":21,"tag":113,"props":743,"children":744},{"style":217},[745],{"type":26,"value":746}," });\n",{"type":21,"tag":113,"props":748,"children":750},{"class":115,"line":749},27,[751],{"type":21,"tag":113,"props":752,"children":753},{"emptyLinePlaceholder":268},[754],{"type":26,"value":271},{"type":21,"tag":113,"props":756,"children":758},{"class":115,"line":757},28,[759,763,768,772,777,782,787,792],{"type":21,"tag":113,"props":760,"children":761},{"style":211},[762],{"type":26,"value":397},{"type":21,"tag":113,"props":764,"children":765},{"style":132},[766],{"type":26,"value":767}," articles",{"type":21,"tag":113,"props":769,"children":770},{"style":211},[771],{"type":26,"value":290},{"type":21,"tag":113,"props":773,"children":774},{"style":211},[775],{"type":26,"value":776}," await",{"type":21,"tag":113,"props":778,"children":779},{"style":120},[780],{"type":26,"value":781}," serverQueryContent",{"type":21,"tag":113,"props":783,"children":784},{"style":217},[785],{"type":26,"value":786},"(event).",{"type":21,"tag":113,"props":788,"children":789},{"style":120},[790],{"type":26,"value":791},"find",{"type":21,"tag":113,"props":793,"children":794},{"style":217},[795],{"type":26,"value":796},"();\n",{"type":21,"tag":113,"props":798,"children":800},{"class":115,"line":799},29,[801],{"type":21,"tag":113,"props":802,"children":803},{"emptyLinePlaceholder":268},[804],{"type":26,"value":271},{"type":21,"tag":113,"props":806,"children":808},{"class":115,"line":807},30,[809,814,819,824,829,833,837],{"type":21,"tag":113,"props":810,"children":811},{"style":217},[812],{"type":26,"value":813}," articles.",{"type":21,"tag":113,"props":815,"children":816},{"style":120},[817],{"type":26,"value":818},"forEach",{"type":21,"tag":113,"props":820,"children":821},{"style":217},[822],{"type":26,"value":823},"((",{"type":21,"tag":113,"props":825,"children":826},{"style":362},[827],{"type":26,"value":828},"article",{"type":21,"tag":113,"props":830,"children":831},{"style":217},[832],{"type":26,"value":370},{"type":21,"tag":113,"props":834,"children":835},{"style":211},[836],{"type":26,"value":375},{"type":21,"tag":113,"props":838,"children":839},{"style":217},[840],{"type":26,"value":380},{"type":21,"tag":113,"props":842,"children":844},{"class":115,"line":843},31,[845,850,855],{"type":21,"tag":113,"props":846,"children":847},{"style":217},[848],{"type":26,"value":849}," feed.",{"type":21,"tag":113,"props":851,"children":852},{"style":120},[853],{"type":26,"value":854},"addItem",{"type":21,"tag":113,"props":856,"children":857},{"style":217},[858],{"type":26,"value":421},{"type":21,"tag":113,"props":860,"children":862},{"class":115,"line":861},32,[863,868,873,878,883,888],{"type":21,"tag":113,"props":864,"children":865},{"style":217},[866],{"type":26,"value":867}," title: article.title ",{"type":21,"tag":113,"props":869,"children":870},{"style":211},[871],{"type":26,"value":872},"?",{"type":21,"tag":113,"props":874,"children":875},{"style":217},[876],{"type":26,"value":877}," article.title ",{"type":21,"tag":113,"props":879,"children":880},{"style":211},[881],{"type":26,"value":882},":",{"type":21,"tag":113,"props":884,"children":885},{"style":126},[886],{"type":26,"value":887}," \"Missing Title\"",{"type":21,"tag":113,"props":889,"children":890},{"style":217},[891],{"type":26,"value":440},{"type":21,"tag":113,"props":893,"children":895},{"class":115,"line":894},33,[896],{"type":21,"tag":113,"props":897,"children":898},{"style":217},[899],{"type":26,"value":900}," id: article._path,\n",{"type":21,"tag":113,"props":902,"children":904},{"class":115,"line":903},34,[905,910,914,918,923,927,931,936,940],{"type":21,"tag":113,"props":906,"children":907},{"style":217},[908],{"type":26,"value":909}," link: ",{"type":21,"tag":113,"props":911,"children":912},{"style":126},[913],{"type":26,"value":525},{"type":21,"tag":113,"props":915,"children":916},{"style":132},[917],{"type":26,"value":472},{"type":21,"tag":113,"props":919,"children":920},{"style":126},[921],{"type":26,"value":922},"}${",{"type":21,"tag":113,"props":924,"children":925},{"style":217},[926],{"type":26,"value":828},{"type":21,"tag":113,"props":928,"children":929},{"style":126},[930],{"type":26,"value":161},{"type":21,"tag":113,"props":932,"children":933},{"style":217},[934],{"type":26,"value":935},"_path",{"type":21,"tag":113,"props":937,"children":938},{"style":126},[939],{"type":26,"value":618},{"type":21,"tag":113,"props":941,"children":942},{"style":217},[943],{"type":26,"value":440},{"type":21,"tag":113,"props":945,"children":947},{"class":115,"line":946},35,[948],{"type":21,"tag":113,"props":949,"children":950},{"style":217},[951],{"type":26,"value":952}," description: article.description,\n",{"type":21,"tag":113,"props":954,"children":956},{"class":115,"line":955},36,[957],{"type":21,"tag":113,"props":958,"children":959},{"style":217},[960],{"type":26,"value":961}," author: [\n",{"type":21,"tag":113,"props":963,"children":965},{"class":115,"line":964},37,[966],{"type":21,"tag":113,"props":967,"children":968},{"style":217},[969],{"type":26,"value":970}," {\n",{"type":21,"tag":113,"props":972,"children":974},{"class":115,"line":973},38,[975,980,984],{"type":21,"tag":113,"props":976,"children":977},{"style":217},[978],{"type":26,"value":979}," name: ",{"type":21,"tag":113,"props":981,"children":982},{"style":132},[983],{"type":26,"value":613},{"type":21,"tag":113,"props":985,"children":986},{"style":217},[987],{"type":26,"value":440},{"type":21,"tag":113,"props":989,"children":991},{"class":115,"line":990},39,[992],{"type":21,"tag":113,"props":993,"children":994},{"style":217},[995],{"type":26,"value":996}," },\n",{"type":21,"tag":113,"props":998,"children":1000},{"class":115,"line":999},40,[1001],{"type":21,"tag":113,"props":1002,"children":1003},{"style":217},[1004],{"type":26,"value":1005}," ],\n",{"type":21,"tag":113,"props":1007,"children":1009},{"class":115,"line":1008},41,[1010,1015,1019,1023],{"type":21,"tag":113,"props":1011,"children":1012},{"style":217},[1013],{"type":26,"value":1014}," date: ",{"type":21,"tag":113,"props":1016,"children":1017},{"style":211},[1018],{"type":26,"value":583},{"type":21,"tag":113,"props":1020,"children":1021},{"style":120},[1022],{"type":26,"value":588},{"type":21,"tag":113,"props":1024,"children":1025},{"style":217},[1026],{"type":26,"value":1027},"(article.date),\n",{"type":21,"tag":113,"props":1029,"children":1031},{"class":115,"line":1030},42,[1032,1037,1041,1046,1050,1055,1059,1063,1068,1072,1077],{"type":21,"tag":113,"props":1033,"children":1034},{"style":217},[1035],{"type":26,"value":1036}," image: article.cover_image ",{"type":21,"tag":113,"props":1038,"children":1039},{"style":211},[1040],{"type":26,"value":872},{"type":21,"tag":113,"props":1042,"children":1043},{"style":126},[1044],{"type":26,"value":1045}," `${",{"type":21,"tag":113,"props":1047,"children":1048},{"style":132},[1049],{"type":26,"value":472},{"type":21,"tag":113,"props":1051,"children":1052},{"style":126},[1053],{"type":26,"value":1054},"}/${",{"type":21,"tag":113,"props":1056,"children":1057},{"style":217},[1058],{"type":26,"value":828},{"type":21,"tag":113,"props":1060,"children":1061},{"style":126},[1062],{"type":26,"value":161},{"type":21,"tag":113,"props":1064,"children":1065},{"style":217},[1066],{"type":26,"value":1067},"cover_image",{"type":21,"tag":113,"props":1069,"children":1070},{"style":126},[1071],{"type":26,"value":618},{"type":21,"tag":113,"props":1073,"children":1074},{"style":211},[1075],{"type":26,"value":1076}," :",{"type":21,"tag":113,"props":1078,"children":1079},{"style":132},[1080],{"type":26,"value":1081}," undefined\n",{"type":21,"tag":113,"props":1083,"children":1085},{"class":115,"line":1084},43,[1086],{"type":21,"tag":113,"props":1087,"children":1088},{"style":217},[1089],{"type":26,"value":1090}," });\n",{"type":21,"tag":113,"props":1092,"children":1094},{"class":115,"line":1093},44,[1095],{"type":21,"tag":113,"props":1096,"children":1097},{"style":217},[1098],{"type":26,"value":746},{"type":21,"tag":113,"props":1100,"children":1102},{"class":115,"line":1101},45,[1103],{"type":21,"tag":113,"props":1104,"children":1105},{"emptyLinePlaceholder":268},[1106],{"type":26,"value":271},{"type":21,"tag":113,"props":1108,"children":1110},{"class":115,"line":1109},46,[1111,1116,1121,1126],{"type":21,"tag":113,"props":1112,"children":1113},{"style":211},[1114],{"type":26,"value":1115}," return",{"type":21,"tag":113,"props":1117,"children":1118},{"style":217},[1119],{"type":26,"value":1120}," feed.",{"type":21,"tag":113,"props":1122,"children":1123},{"style":120},[1124],{"type":26,"value":1125},"atom1",{"type":21,"tag":113,"props":1127,"children":1128},{"style":217},[1129],{"type":26,"value":796},{"type":21,"tag":113,"props":1131,"children":1133},{"class":115,"line":1132},47,[1134],{"type":21,"tag":113,"props":1135,"children":1136},{"style":217},[1137],{"type":26,"value":1138},"});\n",{"type":21,"tag":22,"props":1140,"children":1141},{},[1142,1144,1150,1152,1158,1160,1166,1168,1174],{"type":26,"value":1143},"And that's just about it! Except, if you are statically generating your website with the ",{"type":21,"tag":109,"props":1145,"children":1147},{"className":1146},[],[1148],{"type":26,"value":1149},"nuxt generate",{"type":26,"value":1151}," command, you will need to configure this server-side route to be pre-rendered on site generation. This is as simple as adding a ",{"type":21,"tag":109,"props":1153,"children":1155},{"className":1154},[],[1156],{"type":26,"value":1157},"nitro",{"type":26,"value":1159}," ",{"type":21,"tag":109,"props":1161,"children":1163},{"className":1162},[],[1164],{"type":26,"value":1165},"prerender",{"type":26,"value":1167}," definition in your ",{"type":21,"tag":109,"props":1169,"children":1171},{"className":1170},[],[1172],{"type":26,"value":1173},"nuxt.config.ts",{"type":26,"value":1175}," file, like so:",{"type":21,"tag":102,"props":1177,"children":1179},{"className":199,"code":1178,"language":201,"meta":7,"style":7},"nitro: {\n prerender: {\n routes: ['/atom']\n }\n}\n",[1180],{"type":21,"tag":109,"props":1181,"children":1182},{"__ignoreMap":7},[1183,1195,1207,1230,1238],{"type":21,"tag":113,"props":1184,"children":1185},{"class":115,"line":116},[1186,1190],{"type":21,"tag":113,"props":1187,"children":1188},{"style":120},[1189],{"type":26,"value":1157},{"type":21,"tag":113,"props":1191,"children":1192},{"style":217},[1193],{"type":26,"value":1194},": {\n",{"type":21,"tag":113,"props":1196,"children":1197},{"class":115,"line":238},[1198,1203],{"type":21,"tag":113,"props":1199,"children":1200},{"style":120},[1201],{"type":26,"value":1202}," prerender",{"type":21,"tag":113,"props":1204,"children":1205},{"style":217},[1206],{"type":26,"value":1194},{"type":21,"tag":113,"props":1208,"children":1209},{"class":115,"line":264},[1210,1215,1220,1225],{"type":21,"tag":113,"props":1211,"children":1212},{"style":120},[1213],{"type":26,"value":1214}," routes",{"type":21,"tag":113,"props":1216,"children":1217},{"style":217},[1218],{"type":26,"value":1219},": [",{"type":21,"tag":113,"props":1221,"children":1222},{"style":126},[1223],{"type":26,"value":1224},"'/atom'",{"type":21,"tag":113,"props":1226,"children":1227},{"style":217},[1228],{"type":26,"value":1229},"]\n",{"type":21,"tag":113,"props":1231,"children":1232},{"class":115,"line":274},[1233],{"type":21,"tag":113,"props":1234,"children":1235},{"style":217},[1236],{"type":26,"value":1237}," }\n",{"type":21,"tag":113,"props":1239,"children":1240},{"class":115,"line":298},[1241],{"type":21,"tag":113,"props":1242,"children":1243},{"style":217},[1244],{"type":26,"value":1245},"}\n",{"type":21,"tag":52,"props":1247,"children":1249},{"id":1248},"bonus",[1250],{"type":26,"value":1251},"Bonus",{"type":21,"tag":22,"props":1253,"children":1254},{},[1255,1257,1263],{"type":26,"value":1256},"You may also be interested in adding a ",{"type":21,"tag":109,"props":1258,"children":1260},{"className":1259},[],[1261],{"type":26,"value":1262},"sitemap.xml",{"type":26,"value":1264}," to your website. This can be done in almost an identical fashion!",{"type":21,"tag":22,"props":1266,"children":1267},{},[1268],{"type":26,"value":1269},"Install the dependency:",{"type":21,"tag":102,"props":1271,"children":1273},{"className":104,"code":1272,"language":106,"meta":7,"style":7},"npm i -D sitemap\n",[1274],{"type":21,"tag":109,"props":1275,"children":1276},{"__ignoreMap":7},[1277],{"type":21,"tag":113,"props":1278,"children":1279},{"class":115,"line":116},[1280,1284,1288,1292],{"type":21,"tag":113,"props":1281,"children":1282},{"style":120},[1283],{"type":26,"value":123},{"type":21,"tag":113,"props":1285,"children":1286},{"style":126},[1287],{"type":26,"value":129},{"type":21,"tag":113,"props":1289,"children":1290},{"style":132},[1291],{"type":26,"value":135},{"type":21,"tag":113,"props":1293,"children":1294},{"style":126},[1295],{"type":26,"value":1296}," sitemap\n",{"type":21,"tag":22,"props":1298,"children":1299},{},[1300,1302,1308],{"type":26,"value":1301},"Create a route at ",{"type":21,"tag":109,"props":1303,"children":1305},{"className":1304},[],[1306],{"type":26,"value":1307},"server/routes/sitemap.xml.ts",{"type":26,"value":882},{"type":21,"tag":102,"props":1310,"children":1312},{"className":199,"code":1311,"language":201,"meta":7,"style":7},"import { serverQueryContent } from '#content/server';\nimport { SitemapStream, streamToPromise } from 'sitemap';\n\nexport default defineEventHandler(async (event) => {\n const articles = await serverQueryContent(event).find();\n\n const sitemap = new SitemapStream({ hostname: 'https://my-website.com/' });\n\n // Add non nuxt content endpoints here\n sitemap.write({ url: '/' });\n sitemap.write({ url: '/articles' });\n\n // Dynamically generate routes for Nuxt markdown content\n articles.forEach((article) => sitemap.write({ url: article._path, changefreq: 'monthly' }));\n sitemap.end();\n\n return (await streamToPromise(sitemap));\n});\n",[1313],{"type":21,"tag":109,"props":1314,"children":1315},{"__ignoreMap":7},[1316,1339,1364,1371,1414,1449,1456,1496,1503,1512,1539,1563,1570,1578,1629,1645,1652,1678],{"type":21,"tag":113,"props":1317,"children":1318},{"class":115,"line":116},[1319,1323,1327,1331,1335],{"type":21,"tag":113,"props":1320,"children":1321},{"style":211},[1322],{"type":26,"value":214},{"type":21,"tag":113,"props":1324,"children":1325},{"style":217},[1326],{"type":26,"value":220},{"type":21,"tag":113,"props":1328,"children":1329},{"style":211},[1330],{"type":26,"value":225},{"type":21,"tag":113,"props":1332,"children":1333},{"style":126},[1334],{"type":26,"value":230},{"type":21,"tag":113,"props":1336,"children":1337},{"style":217},[1338],{"type":26,"value":235},{"type":21,"tag":113,"props":1340,"children":1341},{"class":115,"line":238},[1342,1346,1351,1355,1360],{"type":21,"tag":113,"props":1343,"children":1344},{"style":211},[1345],{"type":26,"value":214},{"type":21,"tag":113,"props":1347,"children":1348},{"style":217},[1349],{"type":26,"value":1350}," { SitemapStream, streamToPromise } ",{"type":21,"tag":113,"props":1352,"children":1353},{"style":211},[1354],{"type":26,"value":225},{"type":21,"tag":113,"props":1356,"children":1357},{"style":126},[1358],{"type":26,"value":1359}," 'sitemap'",{"type":21,"tag":113,"props":1361,"children":1362},{"style":217},[1363],{"type":26,"value":235},{"type":21,"tag":113,"props":1365,"children":1366},{"class":115,"line":264},[1367],{"type":21,"tag":113,"props":1368,"children":1369},{"emptyLinePlaceholder":268},[1370],{"type":26,"value":271},{"type":21,"tag":113,"props":1372,"children":1373},{"class":115,"line":274},[1374,1378,1382,1386,1390,1394,1398,1402,1406,1410],{"type":21,"tag":113,"props":1375,"children":1376},{"style":211},[1377],{"type":26,"value":334},{"type":21,"tag":113,"props":1379,"children":1380},{"style":211},[1381],{"type":26,"value":339},{"type":21,"tag":113,"props":1383,"children":1384},{"style":120},[1385],{"type":26,"value":344},{"type":21,"tag":113,"props":1387,"children":1388},{"style":217},[1389],{"type":26,"value":349},{"type":21,"tag":113,"props":1391,"children":1392},{"style":211},[1393],{"type":26,"value":354},{"type":21,"tag":113,"props":1395,"children":1396},{"style":217},[1397],{"type":26,"value":359},{"type":21,"tag":113,"props":1399,"children":1400},{"style":362},[1401],{"type":26,"value":365},{"type":21,"tag":113,"props":1403,"children":1404},{"style":217},[1405],{"type":26,"value":370},{"type":21,"tag":113,"props":1407,"children":1408},{"style":211},[1409],{"type":26,"value":375},{"type":21,"tag":113,"props":1411,"children":1412},{"style":217},[1413],{"type":26,"value":380},{"type":21,"tag":113,"props":1415,"children":1416},{"class":115,"line":298},[1417,1421,1425,1429,1433,1437,1441,1445],{"type":21,"tag":113,"props":1418,"children":1419},{"style":211},[1420],{"type":26,"value":397},{"type":21,"tag":113,"props":1422,"children":1423},{"style":132},[1424],{"type":26,"value":767},{"type":21,"tag":113,"props":1426,"children":1427},{"style":211},[1428],{"type":26,"value":290},{"type":21,"tag":113,"props":1430,"children":1431},{"style":211},[1432],{"type":26,"value":776},{"type":21,"tag":113,"props":1434,"children":1435},{"style":120},[1436],{"type":26,"value":781},{"type":21,"tag":113,"props":1438,"children":1439},{"style":217},[1440],{"type":26,"value":786},{"type":21,"tag":113,"props":1442,"children":1443},{"style":120},[1444],{"type":26,"value":791},{"type":21,"tag":113,"props":1446,"children":1447},{"style":217},[1448],{"type":26,"value":796},{"type":21,"tag":113,"props":1450,"children":1451},{"class":115,"line":320},[1452],{"type":21,"tag":113,"props":1453,"children":1454},{"emptyLinePlaceholder":268},[1455],{"type":26,"value":271},{"type":21,"tag":113,"props":1457,"children":1458},{"class":115,"line":328},[1459,1463,1468,1472,1476,1481,1486,1491],{"type":21,"tag":113,"props":1460,"children":1461},{"style":211},[1462],{"type":26,"value":397},{"type":21,"tag":113,"props":1464,"children":1465},{"style":132},[1466],{"type":26,"value":1467}," sitemap",{"type":21,"tag":113,"props":1469,"children":1470},{"style":211},[1471],{"type":26,"value":290},{"type":21,"tag":113,"props":1473,"children":1474},{"style":211},[1475],{"type":26,"value":411},{"type":21,"tag":113,"props":1477,"children":1478},{"style":120},[1479],{"type":26,"value":1480}," SitemapStream",{"type":21,"tag":113,"props":1482,"children":1483},{"style":217},[1484],{"type":26,"value":1485},"({ hostname: ",{"type":21,"tag":113,"props":1487,"children":1488},{"style":126},[1489],{"type":26,"value":1490},"'https://my-website.com/'",{"type":21,"tag":113,"props":1492,"children":1493},{"style":217},[1494],{"type":26,"value":1495}," });\n",{"type":21,"tag":113,"props":1497,"children":1498},{"class":115,"line":383},[1499],{"type":21,"tag":113,"props":1500,"children":1501},{"emptyLinePlaceholder":268},[1502],{"type":26,"value":271},{"type":21,"tag":113,"props":1504,"children":1505},{"class":115,"line":391},[1506],{"type":21,"tag":113,"props":1507,"children":1509},{"style":1508},"--shiki-default:#6A737D",[1510],{"type":26,"value":1511}," // Add non nuxt content endpoints here\n",{"type":21,"tag":113,"props":1513,"children":1514},{"class":115,"line":424},[1515,1520,1525,1530,1535],{"type":21,"tag":113,"props":1516,"children":1517},{"style":217},[1518],{"type":26,"value":1519}," sitemap.",{"type":21,"tag":113,"props":1521,"children":1522},{"style":120},[1523],{"type":26,"value":1524},"write",{"type":21,"tag":113,"props":1526,"children":1527},{"style":217},[1528],{"type":26,"value":1529},"({ url: ",{"type":21,"tag":113,"props":1531,"children":1532},{"style":126},[1533],{"type":26,"value":1534},"'/'",{"type":21,"tag":113,"props":1536,"children":1537},{"style":217},[1538],{"type":26,"value":1495},{"type":21,"tag":113,"props":1540,"children":1541},{"class":115,"line":443},[1542,1546,1550,1554,1559],{"type":21,"tag":113,"props":1543,"children":1544},{"style":217},[1545],{"type":26,"value":1519},{"type":21,"tag":113,"props":1547,"children":1548},{"style":120},[1549],{"type":26,"value":1524},{"type":21,"tag":113,"props":1551,"children":1552},{"style":217},[1553],{"type":26,"value":1529},{"type":21,"tag":113,"props":1555,"children":1556},{"style":126},[1557],{"type":26,"value":1558},"'/articles'",{"type":21,"tag":113,"props":1560,"children":1561},{"style":217},[1562],{"type":26,"value":1495},{"type":21,"tag":113,"props":1564,"children":1565},{"class":115,"line":461},[1566],{"type":21,"tag":113,"props":1567,"children":1568},{"emptyLinePlaceholder":268},[1569],{"type":26,"value":271},{"type":21,"tag":113,"props":1571,"children":1572},{"class":115,"line":479},[1573],{"type":21,"tag":113,"props":1574,"children":1575},{"style":1508},[1576],{"type":26,"value":1577}," // Dynamically generate routes for Nuxt markdown content\n",{"type":21,"tag":113,"props":1579,"children":1580},{"class":115,"line":496},[1581,1585,1589,1593,1597,1601,1605,1610,1614,1619,1624],{"type":21,"tag":113,"props":1582,"children":1583},{"style":217},[1584],{"type":26,"value":813},{"type":21,"tag":113,"props":1586,"children":1587},{"style":120},[1588],{"type":26,"value":818},{"type":21,"tag":113,"props":1590,"children":1591},{"style":217},[1592],{"type":26,"value":823},{"type":21,"tag":113,"props":1594,"children":1595},{"style":362},[1596],{"type":26,"value":828},{"type":21,"tag":113,"props":1598,"children":1599},{"style":217},[1600],{"type":26,"value":370},{"type":21,"tag":113,"props":1602,"children":1603},{"style":211},[1604],{"type":26,"value":375},{"type":21,"tag":113,"props":1606,"children":1607},{"style":217},[1608],{"type":26,"value":1609}," sitemap.",{"type":21,"tag":113,"props":1611,"children":1612},{"style":120},[1613],{"type":26,"value":1524},{"type":21,"tag":113,"props":1615,"children":1616},{"style":217},[1617],{"type":26,"value":1618},"({ url: article._path, changefreq: ",{"type":21,"tag":113,"props":1620,"children":1621},{"style":126},[1622],{"type":26,"value":1623},"'monthly'",{"type":21,"tag":113,"props":1625,"children":1626},{"style":217},[1627],{"type":26,"value":1628}," }));\n",{"type":21,"tag":113,"props":1630,"children":1631},{"class":115,"line":514},[1632,1636,1641],{"type":21,"tag":113,"props":1633,"children":1634},{"style":217},[1635],{"type":26,"value":1519},{"type":21,"tag":113,"props":1637,"children":1638},{"style":120},[1639],{"type":26,"value":1640},"end",{"type":21,"tag":113,"props":1642,"children":1643},{"style":217},[1644],{"type":26,"value":796},{"type":21,"tag":113,"props":1646,"children":1647},{"class":115,"line":541},[1648],{"type":21,"tag":113,"props":1649,"children":1650},{"emptyLinePlaceholder":268},[1651],{"type":26,"value":271},{"type":21,"tag":113,"props":1653,"children":1654},{"class":115,"line":567},[1655,1659,1663,1668,1673],{"type":21,"tag":113,"props":1656,"children":1657},{"style":211},[1658],{"type":26,"value":1115},{"type":21,"tag":113,"props":1660,"children":1661},{"style":217},[1662],{"type":26,"value":359},{"type":21,"tag":113,"props":1664,"children":1665},{"style":211},[1666],{"type":26,"value":1667},"await",{"type":21,"tag":113,"props":1669,"children":1670},{"style":120},[1671],{"type":26,"value":1672}," streamToPromise",{"type":21,"tag":113,"props":1674,"children":1675},{"style":217},[1676],{"type":26,"value":1677},"(sitemap));\n",{"type":21,"tag":113,"props":1679,"children":1680},{"class":115,"line":625},[1681],{"type":21,"tag":113,"props":1682,"children":1683},{"style":217},[1684],{"type":26,"value":1138},{"type":21,"tag":22,"props":1686,"children":1687},{},[1688,1690,1695,1697,1702],{"type":26,"value":1689},"And add the ",{"type":21,"tag":109,"props":1691,"children":1693},{"className":1692},[],[1694],{"type":26,"value":1165},{"type":26,"value":1696}," entry in your ",{"type":21,"tag":109,"props":1698,"children":1700},{"className":1699},[],[1701],{"type":26,"value":1173},{"type":26,"value":882},{"type":21,"tag":102,"props":1704,"children":1706},{"className":199,"code":1705,"language":201,"meta":7,"style":7},"nitro: {\n prerender: {\n routes: ['/sitemap.xml', '/atom']\n }\n}\n",[1707],{"type":21,"tag":109,"props":1708,"children":1709},{"__ignoreMap":7},[1710,1721,1732,1761,1768],{"type":21,"tag":113,"props":1711,"children":1712},{"class":115,"line":116},[1713,1717],{"type":21,"tag":113,"props":1714,"children":1715},{"style":120},[1716],{"type":26,"value":1157},{"type":21,"tag":113,"props":1718,"children":1719},{"style":217},[1720],{"type":26,"value":1194},{"type":21,"tag":113,"props":1722,"children":1723},{"class":115,"line":238},[1724,1728],{"type":21,"tag":113,"props":1725,"children":1726},{"style":120},[1727],{"type":26,"value":1202},{"type":21,"tag":113,"props":1729,"children":1730},{"style":217},[1731],{"type":26,"value":1194},{"type":21,"tag":113,"props":1733,"children":1734},{"class":115,"line":264},[1735,1739,1743,1748,1753,1757],{"type":21,"tag":113,"props":1736,"children":1737},{"style":120},[1738],{"type":26,"value":1214},{"type":21,"tag":113,"props":1740,"children":1741},{"style":217},[1742],{"type":26,"value":1219},{"type":21,"tag":113,"props":1744,"children":1745},{"style":126},[1746],{"type":26,"value":1747},"'/sitemap.xml'",{"type":21,"tag":113,"props":1749,"children":1750},{"style":217},[1751],{"type":26,"value":1752},", ",{"type":21,"tag":113,"props":1754,"children":1755},{"style":126},[1756],{"type":26,"value":1224},{"type":21,"tag":113,"props":1758,"children":1759},{"style":217},[1760],{"type":26,"value":1229},{"type":21,"tag":113,"props":1762,"children":1763},{"class":115,"line":274},[1764],{"type":21,"tag":113,"props":1765,"children":1766},{"style":217},[1767],{"type":26,"value":1237},{"type":21,"tag":113,"props":1769,"children":1770},{"class":115,"line":298},[1771],{"type":21,"tag":113,"props":1772,"children":1773},{"style":217},[1774],{"type":26,"value":1245},{"type":21,"tag":1776,"props":1777,"children":1778},"style",{},[1779],{"type":26,"value":1780},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":238,"depth":238,"links":1782},[1783,1784,1785],{"id":54,"depth":238,"text":57},{"id":83,"depth":238,"text":86},{"id":1248,"depth":238,"text":1251},"markdown","content:articles:nuxt-content-rss-feed.md","content","articles/nuxt-content-rss-feed.md","md",1727638398039] \ No newline at end of file diff --git a/articles/nuxt-content-rss-feed/index.html b/articles/nuxt-content-rss-feed/index.html index f53474d9..735739c7 100644 --- a/articles/nuxt-content-rss-feed/index.html +++ b/articles/nuxt-content-rss-feed/index.html @@ -4,33 +4,32 @@ - - + + - - - - + + + + - - + - - - - - - - - - - - - - -
            Category

            How To Add an RSS Feed to a Nuxt Website

            If you are a user of Nuxt Content and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application.

            Preface

            In version 2 of Nuxt, the community module, nuxt-community/feed-module was a popular choice for adding an RSS feed to your website. However, there has been an unresolved open issue since April 1st, 2022 to add support for Nuxt v3. Thankfully, implementing this feature without a module is relatively straight forward.

            Instructions

            First, install the feed library into your project:

            npm i -D feed
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            Category

            How To Add an RSS Feed to a Nuxt Website

            If you are a user of Nuxt Content and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application.

            Preface

            In version 2 of Nuxt, the community module, nuxt-community/feed-module was a popular choice for adding an RSS feed to your website. However, there has been an unresolved open issue since April 1st, 2022 to add support for Nuxt v3. Thankfully, implementing this feature without a module is relatively straight forward.

            Instructions

            First, install the feed library into your project:

            npm i -D feed
             

            Then, create a server/ folder in your project if it does not already exist, and create a file named server/routes/atom.ts.

            Here, we will leverage the feed library and construct an XML representation of our Nuxt content. As you can see, we first define our feed with metadata associated with our RSS feed. This will be used by RSS readers to provide context to the end user. Then, we query our Nuxt content with serverQueryContent and append a feed.addItem for each article.

            import { serverQueryContent } from '#content/server';
             import { Feed } from 'feed';
             
            @@ -107,5 +106,5 @@
                 routes: ['/sitemap.xml', '/atom']
               }
             }
            -
            - \ No newline at end of file +
            + \ No newline at end of file diff --git a/articles/nuxt-v3-migration/_payload.json b/articles/nuxt-v3-migration/_payload.json index 78089f1d..d2305f4d 100644 --- a/articles/nuxt-v3-migration/_payload.json +++ b/articles/nuxt-v3-migration/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":125},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"tags":11,"categories":13,"excerpt":15,"body":25,"_type":119,"_id":120,"_source":121,"_file":122,"_stem":123,"_extension":124},"/articles/nuxt-v3-migration","articles",false,"","This Website Has Been Migrated to Nuxt 3 🎉","This website has been migrated to the latest version of the Nuxt web framework, and with it comes all of the exciting goodies that the Vue and Nuxt teams have been concocting over the past few years.\nNot to mention, all of the great plugins in the Vue ecosystem!","2022-12-31",[12],"nuxt",[14],"web",{"type":16,"children":17},"root",[18],{"type":19,"tag":20,"props":21,"children":22},"element","p",{},[23],{"type":24,"value":9},"text",{"type":16,"children":26,"toc":116},[27,31,47,56,61,66,111],{"type":19,"tag":20,"props":28,"children":29},{},[30],{"type":24,"value":9},{"type":19,"tag":20,"props":32,"children":33},{},[34,36,45],{"type":24,"value":35},"If you're curious what changes were required to make the migration, you can check out ",{"type":19,"tag":37,"props":38,"children":42},"a",{"href":39,"rel":40},"https://github.com/cmpadden/cmpadden.github.io/pull/3",[41],"nofollow",[43],{"type":24,"value":44},"pull request #3",{"type":24,"value":46}," in the GitHub repository.",{"type":19,"tag":20,"props":48,"children":49},{},[50],{"type":19,"tag":51,"props":52,"children":55},"img",{"alt":53,"src":54},"Screenshot of Nuxt Migration Pull Request","/images/nuxt-migration-pr.png",[],{"type":19,"tag":20,"props":57,"children":58},{},[59],{"type":24,"value":60},"While the documentation for making this migration is great, there were many breaking changes, and the overall process was quite tedious.\nFor this reason, I opted to generate a new project entirely, and port existing code to this clean slate.\nI believe that this resulted in a project with a bit less cruft.",{"type":19,"tag":20,"props":62,"children":63},{},[64],{"type":24,"value":65},"The most valuable resources for making these changes include:",{"type":19,"tag":67,"props":68,"children":69},"ul",{},[70,81,91,101],{"type":19,"tag":71,"props":72,"children":73},"li",{},[74],{"type":19,"tag":37,"props":75,"children":78},{"href":76,"rel":77},"https://nuxt.com/docs/migration/overview",[41],[79],{"type":24,"value":80},"The Nuxt Migration Guide",{"type":19,"tag":71,"props":82,"children":83},{},[84],{"type":19,"tag":37,"props":85,"children":88},{"href":86,"rel":87},"https://nuxt.com/docs/getting-started/introduction",[41],[89],{"type":24,"value":90},"The Nuxt Framework Guide",{"type":19,"tag":71,"props":92,"children":93},{},[94],{"type":19,"tag":37,"props":95,"children":98},{"href":96,"rel":97},"https://tailwindcss.nuxt.dev/",[41],[99],{"type":24,"value":100},"Nuxt Tailwind Module Documentation",{"type":19,"tag":71,"props":102,"children":103},{},[104],{"type":19,"tag":37,"props":105,"children":108},{"href":106,"rel":107},"https://content.nuxtjs.org/",[41],[109],{"type":24,"value":110},"Nuxt Content Module Documentation",{"type":19,"tag":20,"props":112,"children":113},{},[114],{"type":24,"value":115},"Part of the delay for doing this upgrade was in waiting for module developers to support this major release.\nI'm super thankful for all of the hard work they've don, and I'm excited to explore all of the new features available!\nI just hope that the breaking changes in this release don't cause too much fracturing of the community, as it does feel like déjà vu of Python 2 and 3.",{"title":7,"searchDepth":117,"depth":117,"links":118},2,[],"markdown","content:articles:nuxt-v3-migration.md","content","articles/nuxt-v3-migration.md","articles/nuxt-v3-migration","md",1726174739514] \ No newline at end of file +[{"data":1,"prerenderedAt":124},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"tags":11,"categories":13,"excerpt":15,"body":25,"_type":119,"_id":120,"_source":121,"_file":122,"_extension":123},"/articles/nuxt-v3-migration","articles",false,"","This Website Has Been Migrated to Nuxt 3 🎉","This website has been migrated to the latest version of the Nuxt web framework, and with it comes all of the exciting goodies that the Vue and Nuxt teams have been concocting over the past few years.\nNot to mention, all of the great plugins in the Vue ecosystem!","2022-12-31",[12],"nuxt",[14],"web",{"type":16,"children":17},"root",[18],{"type":19,"tag":20,"props":21,"children":22},"element","p",{},[23],{"type":24,"value":9},"text",{"type":16,"children":26,"toc":116},[27,31,47,56,61,66,111],{"type":19,"tag":20,"props":28,"children":29},{},[30],{"type":24,"value":9},{"type":19,"tag":20,"props":32,"children":33},{},[34,36,45],{"type":24,"value":35},"If you're curious what changes were required to make the migration, you can check out ",{"type":19,"tag":37,"props":38,"children":42},"a",{"href":39,"rel":40},"https://github.com/cmpadden/cmpadden.github.io/pull/3",[41],"nofollow",[43],{"type":24,"value":44},"pull request #3",{"type":24,"value":46}," in the GitHub repository.",{"type":19,"tag":20,"props":48,"children":49},{},[50],{"type":19,"tag":51,"props":52,"children":55},"img",{"alt":53,"src":54},"Screenshot of Nuxt Migration Pull Request","/images/nuxt-migration-pr.png",[],{"type":19,"tag":20,"props":57,"children":58},{},[59],{"type":24,"value":60},"While the documentation for making this migration is great, there were many breaking changes, and the overall process was quite tedious.\nFor this reason, I opted to generate a new project entirely, and port existing code to this clean slate.\nI believe that this resulted in a project with a bit less cruft.",{"type":19,"tag":20,"props":62,"children":63},{},[64],{"type":24,"value":65},"The most valuable resources for making these changes include:",{"type":19,"tag":67,"props":68,"children":69},"ul",{},[70,81,91,101],{"type":19,"tag":71,"props":72,"children":73},"li",{},[74],{"type":19,"tag":37,"props":75,"children":78},{"href":76,"rel":77},"https://nuxt.com/docs/migration/overview",[41],[79],{"type":24,"value":80},"The Nuxt Migration Guide",{"type":19,"tag":71,"props":82,"children":83},{},[84],{"type":19,"tag":37,"props":85,"children":88},{"href":86,"rel":87},"https://nuxt.com/docs/getting-started/introduction",[41],[89],{"type":24,"value":90},"The Nuxt Framework Guide",{"type":19,"tag":71,"props":92,"children":93},{},[94],{"type":19,"tag":37,"props":95,"children":98},{"href":96,"rel":97},"https://tailwindcss.nuxt.dev/",[41],[99],{"type":24,"value":100},"Nuxt Tailwind Module Documentation",{"type":19,"tag":71,"props":102,"children":103},{},[104],{"type":19,"tag":37,"props":105,"children":108},{"href":106,"rel":107},"https://content.nuxtjs.org/",[41],[109],{"type":24,"value":110},"Nuxt Content Module Documentation",{"type":19,"tag":20,"props":112,"children":113},{},[114],{"type":24,"value":115},"Part of the delay for doing this upgrade was in waiting for module developers to support this major release.\nI'm super thankful for all of the hard work they've don, and I'm excited to explore all of the new features available!\nI just hope that the breaking changes in this release don't cause too much fracturing of the community, as it does feel like déjà vu of Python 2 and 3.",{"title":7,"searchDepth":117,"depth":117,"links":118},2,[],"markdown","content:articles:nuxt-v3-migration.md","content","articles/nuxt-v3-migration.md","md",1727638398048] \ No newline at end of file diff --git a/articles/nuxt-v3-migration/index.html b/articles/nuxt-v3-migration/index.html index 2fc39cfb..7775c4e8 100644 --- a/articles/nuxt-v3-migration/index.html +++ b/articles/nuxt-v3-migration/index.html @@ -4,32 +4,31 @@ - - + + - - - - + + + + - - + - - - - - - - - - - - -
            Category
            Tags

            This Website Has Been Migrated to Nuxt 3 🎉

            This website has been migrated to the latest version of the Nuxt web framework, and with it comes all of the exciting goodies that the Vue and Nuxt teams have been concocting over the past few years. + + + + + + + + + + + +

            Category
            Tags

            This Website Has Been Migrated to Nuxt 3 🎉

            This website has been migrated to the latest version of the Nuxt web framework, and with it comes all of the exciting goodies that the Vue and Nuxt teams have been concocting over the past few years. Not to mention, all of the great plugins in the Vue ecosystem!

            If you're curious what changes were required to make the migration, you can check out pull request #3 in the GitHub repository.

            Screenshot of Nuxt Migration Pull Request

            While the documentation for making this migration is great, there were many breaking changes, and the overall process was quite tedious. For this reason, I opted to generate a new project entirely, and port existing code to this clean slate. I believe that this resulted in a project with a bit less cruft.

            The most valuable resources for making these changes include:

            Part of the delay for doing this upgrade was in waiting for module developers to support this major release. I'm super thankful for all of the hard work they've don, and I'm excited to explore all of the new features available! -I just hope that the breaking changes in this release don't cause too much fracturing of the community, as it does feel like déjà vu of Python 2 and 3.

            - \ No newline at end of file +I just hope that the breaking changes in this release don't cause too much fracturing of the community, as it does feel like déjà vu of Python 2 and 3.

            + \ No newline at end of file diff --git a/articles/persistent-archlinux-usb/_payload.json b/articles/persistent-archlinux-usb/_payload.json index 6569bf05..9dde081b 100644 --- a/articles/persistent-archlinux-usb/_payload.json +++ b/articles/persistent-archlinux-usb/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":1337},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"draft":6,"tags":11,"categories":14,"excerpt":16,"body":26,"_type":1331,"_id":1332,"_source":1333,"_file":1334,"_stem":1335,"_extension":1336},"/articles/persistent-archlinux-usb","articles",false,"","Create a Persistent Arch Linux Bootable USB with Vagrant","When installing a linux distribution, it is common for the instructions to have\nthe user create a bootable USB, boot from the device, and proceed with the\ninstallation procedure from that live medium. However, this blog post will\noutline an alternative approach where a virtual machine created with Vagrant\nwill be used in favor of the live medium.","2020-01-09",[12,13],"vagrant","archlinux",[15],"linux",{"type":17,"children":18},"root",[19],{"type":20,"tag":21,"props":22,"children":23},"element","p",{},[24],{"type":25,"value":9},"text",{"type":17,"children":27,"toc":1320},[28,32,39,85,91,98,115,152,165,190,246,354,367,388,654,660,674,681,705,825,831,846,885,908,941,947,1002,1067,1073,1081,1089,1097,1120,1128,1133,1138,1144,1174,1204,1210,1314],{"type":20,"tag":21,"props":29,"children":30},{},[31],{"type":25,"value":9},{"type":20,"tag":33,"props":34,"children":36},"h1",{"id":35},"preface",[37],{"type":25,"value":38},"Preface",{"type":20,"tag":21,"props":40,"children":41},{},[42,44,51,53,83],{"type":25,"value":43},"The original intention was to use Docker for this process -- leveraging the\n",{"type":20,"tag":45,"props":46,"children":48},"code",{"className":47},[],[49],{"type":25,"value":50},"--device",{"type":25,"value":52}," flag and mounting the target USB device in the Docker container,\nbut the underlying hypervisor in Docker Desktop for Mac does not support this.\n",{"type":20,"tag":54,"props":55,"children":56},"sup",{},[57,66,68,75,76],{"type":20,"tag":58,"props":59,"children":63},"a",{"href":60,"rel":61},"https://docs.docker.com/docker-for-mac/docker-toolbox/",[62],"nofollow",[64],{"type":25,"value":65},"1",{"type":25,"value":67}," ",{"type":20,"tag":58,"props":69,"children":72},{"href":70,"rel":71},"https://github.com/moby/hyperkit",[62],[73],{"type":25,"value":74},"2",{"type":25,"value":67},{"type":20,"tag":58,"props":77,"children":80},{"href":78,"rel":79},"https://github.com/docker/for-mac/issues/900",[62],[81],{"type":25,"value":82},"3",{"type":25,"value":84}," While there are workarounds using Docker\nMachine, Vagrant felt like the path of least resistance.",{"type":20,"tag":33,"props":86,"children":88},{"id":87},"instructions",[89],{"type":25,"value":90},"Instructions",{"type":20,"tag":92,"props":93,"children":95},"h2",{"id":94},"create-an-arch-linux-virtual-machine-with-vagrant",[96],{"type":25,"value":97},"Create an Arch Linux Virtual Machine with Vagrant",{"type":20,"tag":21,"props":99,"children":100},{},[101,103,113],{"type":25,"value":102},"Get the latest Arch Linux image ",{"type":20,"tag":54,"props":104,"children":105},{},[106],{"type":20,"tag":58,"props":107,"children":110},{"href":108,"rel":109},"https://app.vagrantup.com/archlinux/boxes/archlinux",[62],[111],{"type":25,"value":112},"4",{"type":25,"value":114}," from the Vagrant Cloud Box\nCatalog.",{"type":20,"tag":116,"props":117,"children":121},"pre",{"code":118,"language":119,"meta":7,"className":120,"style":7},"vagrant box add archlinux/archlinux\n","bash","language-bash shiki shiki-themes github-light",[122],{"type":20,"tag":45,"props":123,"children":124},{"__ignoreMap":7},[125],{"type":20,"tag":126,"props":127,"children":130},"span",{"class":128,"line":129},"line",1,[131,136,142,147],{"type":20,"tag":126,"props":132,"children":134},{"style":133},"--shiki-default:#6F42C1",[135],{"type":25,"value":12},{"type":20,"tag":126,"props":137,"children":139},{"style":138},"--shiki-default:#032F62",[140],{"type":25,"value":141}," box",{"type":20,"tag":126,"props":143,"children":144},{"style":138},[145],{"type":25,"value":146}," add",{"type":20,"tag":126,"props":148,"children":149},{"style":138},[150],{"type":25,"value":151}," archlinux/archlinux\n",{"type":20,"tag":21,"props":153,"children":154},{},[155,157,163],{"type":25,"value":156},"Determine the USB vendor information for the thumb-drive that we will\npass-through to the virtual machine. Using the ",{"type":20,"tag":45,"props":158,"children":160},{"className":159},[],[161],{"type":25,"value":162},"VBoxManage",{"type":25,"value":164}," utility that comes\nwith Virtual Box, list the devices, and make note of the Vendor and Product ID.",{"type":20,"tag":116,"props":166,"children":168},{"code":167,"language":119,"meta":7,"className":120,"style":7}," VBoxManage list usbhost\n",[169],{"type":20,"tag":45,"props":170,"children":171},{"__ignoreMap":7},[172],{"type":20,"tag":126,"props":173,"children":174},{"class":128,"line":129},[175,180,185],{"type":20,"tag":126,"props":176,"children":177},{"style":133},[178],{"type":25,"value":179}," VBoxManage",{"type":20,"tag":126,"props":181,"children":182},{"style":138},[183],{"type":25,"value":184}," list",{"type":20,"tag":126,"props":186,"children":187},{"style":138},[188],{"type":25,"value":189}," usbhost\n",{"type":20,"tag":21,"props":191,"children":192},{},[193,195,201,203,209,211,229,231,237,239,244],{"type":25,"value":194},"Create a ",{"type":20,"tag":45,"props":196,"children":198},{"className":197},[],[199],{"type":25,"value":200},"Vagrantfile",{"type":25,"value":202}," with ",{"type":20,"tag":45,"props":204,"children":206},{"className":205},[],[207],{"type":25,"value":208},"archlinx/archlinux",{"type":25,"value":210}," as the target box, and the USB\ndevice information that is passed through. ",{"type":20,"tag":54,"props":212,"children":213},{},[214,221,222],{"type":20,"tag":58,"props":215,"children":218},{"href":216,"rel":217},"https://antonyjepson.wordpress.com/2012/01/26/quickly-attaching-usb-devices-to-virtualbox-guests-using-vboxmanage/",[62],[219],{"type":25,"value":220},"5",{"type":25,"value":67},{"type":20,"tag":58,"props":223,"children":226},{"href":224,"rel":225},"https://gist.github.com/dscape/7d829c0c116ef419f963",[62],[227],{"type":25,"value":228},"6",{"type":25,"value":230}," Vagrant\noffers a handy customization parameter ",{"type":20,"tag":45,"props":232,"children":234},{"className":233},[],[235],{"type":25,"value":236},"vb.customize",{"type":25,"value":238}," that calls the\n",{"type":20,"tag":45,"props":240,"children":242},{"className":241},[],[243],{"type":25,"value":162},{"type":25,"value":245}," command under-the-hood, allowing one to enable the guest machine\nto access the host machine's USB devices.",{"type":20,"tag":116,"props":247,"children":251},{"code":248,"language":249,"meta":7,"className":250,"style":7},"# -*- mode: ruby -*-\n# vi: set ft=ruby :\n\nVagrant.configure(\"2\") do |config|\n config.vm.box = \"archlinux/archlinux\"\n config.vm.provider \"virtualbox\" do |vb|\n vb.name = \"archlinux\"\n vb.customize ['modifyvm', :id, '--usb', 'on']\n vb.customize ['usbfilter', 'add', '1', '--target', :id, '--name', 'SanDisk Ultra Fit', '--vendorid', '0x0781', '--productid', '0x5583']\n end\nend\n","txt","language-txt shiki shiki-themes github-light",[252],{"type":20,"tag":45,"props":253,"children":254},{"__ignoreMap":7},[255,263,272,282,291,300,309,318,327,336,345],{"type":20,"tag":126,"props":256,"children":257},{"class":128,"line":129},[258],{"type":20,"tag":126,"props":259,"children":260},{},[261],{"type":25,"value":262},"# -*- mode: ruby -*-\n",{"type":20,"tag":126,"props":264,"children":266},{"class":128,"line":265},2,[267],{"type":20,"tag":126,"props":268,"children":269},{},[270],{"type":25,"value":271},"# vi: set ft=ruby :\n",{"type":20,"tag":126,"props":273,"children":275},{"class":128,"line":274},3,[276],{"type":20,"tag":126,"props":277,"children":279},{"emptyLinePlaceholder":278},true,[280],{"type":25,"value":281},"\n",{"type":20,"tag":126,"props":283,"children":285},{"class":128,"line":284},4,[286],{"type":20,"tag":126,"props":287,"children":288},{},[289],{"type":25,"value":290},"Vagrant.configure(\"2\") do |config|\n",{"type":20,"tag":126,"props":292,"children":294},{"class":128,"line":293},5,[295],{"type":20,"tag":126,"props":296,"children":297},{},[298],{"type":25,"value":299}," config.vm.box = \"archlinux/archlinux\"\n",{"type":20,"tag":126,"props":301,"children":303},{"class":128,"line":302},6,[304],{"type":20,"tag":126,"props":305,"children":306},{},[307],{"type":25,"value":308}," config.vm.provider \"virtualbox\" do |vb|\n",{"type":20,"tag":126,"props":310,"children":312},{"class":128,"line":311},7,[313],{"type":20,"tag":126,"props":314,"children":315},{},[316],{"type":25,"value":317}," vb.name = \"archlinux\"\n",{"type":20,"tag":126,"props":319,"children":321},{"class":128,"line":320},8,[322],{"type":20,"tag":126,"props":323,"children":324},{},[325],{"type":25,"value":326}," vb.customize ['modifyvm', :id, '--usb', 'on']\n",{"type":20,"tag":126,"props":328,"children":330},{"class":128,"line":329},9,[331],{"type":20,"tag":126,"props":332,"children":333},{},[334],{"type":25,"value":335}," vb.customize ['usbfilter', 'add', '1', '--target', :id, '--name', 'SanDisk Ultra Fit', '--vendorid', '0x0781', '--productid', '0x5583']\n",{"type":20,"tag":126,"props":337,"children":339},{"class":128,"line":338},10,[340],{"type":20,"tag":126,"props":341,"children":342},{},[343],{"type":25,"value":344}," end\n",{"type":20,"tag":126,"props":346,"children":348},{"class":128,"line":347},11,[349],{"type":20,"tag":126,"props":350,"children":351},{},[352],{"type":25,"value":353},"end\n",{"type":20,"tag":21,"props":355,"children":356},{},[357,359,365],{"type":25,"value":358},"When virtual machine is brought up, the ",{"type":20,"tag":45,"props":360,"children":362},{"className":361},[],[363],{"type":25,"value":364},"usbfilter",{"type":25,"value":366}," is applied, and the guest\nis able to access to the host machine's USB device that was specified in the\nfilter.",{"type":20,"tag":21,"props":368,"children":369},{},[370,372,378,380,386],{"type":25,"value":371},"Start the machine, ",{"type":20,"tag":45,"props":373,"children":375},{"className":374},[],[376],{"type":25,"value":377},"ssh",{"type":25,"value":379}," into the guest, and list the devices to confirm that\nthe USB device is available (see: ",{"type":20,"tag":45,"props":381,"children":383},{"className":382},[],[384],{"type":25,"value":385},"/dev/sdb",{"type":25,"value":387},").",{"type":20,"tag":116,"props":389,"children":391},{"code":390,"language":119,"meta":7,"className":120,"style":7},"$ vagrant up\n$ vagrant ssh\n[vagrant@archlinux ~]$ lsblk\nNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT\nsda 8:0 0 20G 0 disk\n├─sda1 8:1 0 1.9G 0 part [SWAP]\n└─sda2 8:2 0 18.1G 0 part /\nsdb 8:16 1 28.7G 0 disk\n└─sdb1 8:17 1 8G 0 part\n",[392],{"type":20,"tag":45,"props":393,"children":394},{"__ignoreMap":7},[395,413,429,449,487,521,557,592,623],{"type":20,"tag":126,"props":396,"children":397},{"class":128,"line":129},[398,403,408],{"type":20,"tag":126,"props":399,"children":400},{"style":133},[401],{"type":25,"value":402},"$",{"type":20,"tag":126,"props":404,"children":405},{"style":138},[406],{"type":25,"value":407}," vagrant",{"type":20,"tag":126,"props":409,"children":410},{"style":138},[411],{"type":25,"value":412}," up\n",{"type":20,"tag":126,"props":414,"children":415},{"class":128,"line":265},[416,420,424],{"type":20,"tag":126,"props":417,"children":418},{"style":133},[419],{"type":25,"value":402},{"type":20,"tag":126,"props":421,"children":422},{"style":138},[423],{"type":25,"value":407},{"type":20,"tag":126,"props":425,"children":426},{"style":138},[427],{"type":25,"value":428}," ssh\n",{"type":20,"tag":126,"props":430,"children":431},{"class":128,"line":274},[432,438,444],{"type":20,"tag":126,"props":433,"children":435},{"style":434},"--shiki-default:#24292E",[436],{"type":25,"value":437},"[vagrant@archlinux ",{"type":20,"tag":126,"props":439,"children":441},{"style":440},"--shiki-default:#D73A49",[442],{"type":25,"value":443},"~",{"type":20,"tag":126,"props":445,"children":446},{"style":434},[447],{"type":25,"value":448},"]$ lsblk\n",{"type":20,"tag":126,"props":450,"children":451},{"class":128,"line":284},[452,457,462,467,472,477,482],{"type":20,"tag":126,"props":453,"children":454},{"style":133},[455],{"type":25,"value":456},"NAME",{"type":20,"tag":126,"props":458,"children":459},{"style":138},[460],{"type":25,"value":461}," MAJ:MIN",{"type":20,"tag":126,"props":463,"children":464},{"style":138},[465],{"type":25,"value":466}," RM",{"type":20,"tag":126,"props":468,"children":469},{"style":138},[470],{"type":25,"value":471}," SIZE",{"type":20,"tag":126,"props":473,"children":474},{"style":138},[475],{"type":25,"value":476}," RO",{"type":20,"tag":126,"props":478,"children":479},{"style":138},[480],{"type":25,"value":481}," TYPE",{"type":20,"tag":126,"props":483,"children":484},{"style":138},[485],{"type":25,"value":486}," MOUNTPOINT\n",{"type":20,"tag":126,"props":488,"children":489},{"class":128,"line":293},[490,495,500,506,511,516],{"type":20,"tag":126,"props":491,"children":492},{"style":133},[493],{"type":25,"value":494},"sda",{"type":20,"tag":126,"props":496,"children":497},{"style":138},[498],{"type":25,"value":499}," 8:0",{"type":20,"tag":126,"props":501,"children":503},{"style":502},"--shiki-default:#005CC5",[504],{"type":25,"value":505}," 0",{"type":20,"tag":126,"props":507,"children":508},{"style":138},[509],{"type":25,"value":510}," 20G",{"type":20,"tag":126,"props":512,"children":513},{"style":502},[514],{"type":25,"value":515}," 0",{"type":20,"tag":126,"props":517,"children":518},{"style":138},[519],{"type":25,"value":520}," disk\n",{"type":20,"tag":126,"props":522,"children":523},{"class":128,"line":302},[524,529,534,538,543,547,552],{"type":20,"tag":126,"props":525,"children":526},{"style":133},[527],{"type":25,"value":528},"├─sda1",{"type":20,"tag":126,"props":530,"children":531},{"style":138},[532],{"type":25,"value":533}," 8:1",{"type":20,"tag":126,"props":535,"children":536},{"style":502},[537],{"type":25,"value":505},{"type":20,"tag":126,"props":539,"children":540},{"style":138},[541],{"type":25,"value":542}," 1.9G",{"type":20,"tag":126,"props":544,"children":545},{"style":502},[546],{"type":25,"value":515},{"type":20,"tag":126,"props":548,"children":549},{"style":138},[550],{"type":25,"value":551}," part",{"type":20,"tag":126,"props":553,"children":554},{"style":434},[555],{"type":25,"value":556}," [SWAP]\n",{"type":20,"tag":126,"props":558,"children":559},{"class":128,"line":311},[560,565,570,574,579,583,587],{"type":20,"tag":126,"props":561,"children":562},{"style":133},[563],{"type":25,"value":564},"└─sda2",{"type":20,"tag":126,"props":566,"children":567},{"style":138},[568],{"type":25,"value":569}," 8:2",{"type":20,"tag":126,"props":571,"children":572},{"style":502},[573],{"type":25,"value":505},{"type":20,"tag":126,"props":575,"children":576},{"style":138},[577],{"type":25,"value":578}," 18.1G",{"type":20,"tag":126,"props":580,"children":581},{"style":502},[582],{"type":25,"value":515},{"type":20,"tag":126,"props":584,"children":585},{"style":138},[586],{"type":25,"value":551},{"type":20,"tag":126,"props":588,"children":589},{"style":138},[590],{"type":25,"value":591}," /\n",{"type":20,"tag":126,"props":593,"children":594},{"class":128,"line":320},[595,600,605,610,615,619],{"type":20,"tag":126,"props":596,"children":597},{"style":133},[598],{"type":25,"value":599},"sdb",{"type":20,"tag":126,"props":601,"children":602},{"style":138},[603],{"type":25,"value":604}," 8:16",{"type":20,"tag":126,"props":606,"children":607},{"style":502},[608],{"type":25,"value":609}," 1",{"type":20,"tag":126,"props":611,"children":612},{"style":138},[613],{"type":25,"value":614}," 28.7G",{"type":20,"tag":126,"props":616,"children":617},{"style":502},[618],{"type":25,"value":515},{"type":20,"tag":126,"props":620,"children":621},{"style":138},[622],{"type":25,"value":520},{"type":20,"tag":126,"props":624,"children":625},{"class":128,"line":329},[626,631,636,640,645,649],{"type":20,"tag":126,"props":627,"children":628},{"style":133},[629],{"type":25,"value":630},"└─sdb1",{"type":20,"tag":126,"props":632,"children":633},{"style":138},[634],{"type":25,"value":635}," 8:17",{"type":20,"tag":126,"props":637,"children":638},{"style":502},[639],{"type":25,"value":609},{"type":20,"tag":126,"props":641,"children":642},{"style":138},[643],{"type":25,"value":644}," 8G",{"type":20,"tag":126,"props":646,"children":647},{"style":502},[648],{"type":25,"value":515},{"type":20,"tag":126,"props":650,"children":651},{"style":138},[652],{"type":25,"value":653}," part\n",{"type":20,"tag":92,"props":655,"children":657},{"id":656},"install-arch-linux-on-the-usb-drive",[658],{"type":25,"value":659},"Install Arch Linux on the USB Drive",{"type":20,"tag":21,"props":661,"children":662},{},[663,665,672],{"type":25,"value":664},"The ",{"type":20,"tag":58,"props":666,"children":669},{"href":667,"rel":668},"https://wiki.archlinux.org/index.php/Installation_guide",[62],[670],{"type":25,"value":671},"Arch Linux Installation Guide",{"type":25,"value":673}," outlines the installation procedure in\ngreat detail -- the following steps follow this closely with a few alteration\ndue to installing onto removable media.",{"type":20,"tag":675,"props":676,"children":678},"h3",{"id":677},"partition-the-disk-uefi-with-gpt",[679],{"type":25,"value":680},"Partition the Disk (UEFI with GPT)",{"type":20,"tag":116,"props":682,"children":684},{"code":683,"language":119,"meta":7,"className":120,"style":7},"[root@archlinux ~]# fdisk /dev/sdb\n",[685],{"type":20,"tag":45,"props":686,"children":687},{"__ignoreMap":7},[688],{"type":20,"tag":126,"props":689,"children":690},{"class":128,"line":129},[691,696,700],{"type":20,"tag":126,"props":692,"children":693},{"style":434},[694],{"type":25,"value":695},"[root@archlinux ",{"type":20,"tag":126,"props":697,"children":698},{"style":440},[699],{"type":25,"value":443},{"type":20,"tag":126,"props":701,"children":702},{"style":434},[703],{"type":25,"value":704},"]# fdisk /dev/sdb\n",{"type":20,"tag":116,"props":706,"children":708},{"code":707,"language":249,"meta":7,"className":250,"style":7},"Command (m for help): p\nDisk /dev/sdb: 28.66 GiB, 30752636928 bytes, 60063744 sectors\nDisk model: Ultra Fit\nUnits: sectors of 1 * 512 = 512 bytes\nSector size (logical/physical): 512 bytes / 512 bytes\nI/O size (minimum/optimal): 512 bytes / 512 bytes\nDisklabel type: gpt\nDisk identifier: E1D6C445-1B79-AB4D-A442-FA4AD6DF4ECC\n\nDevice Start End Sectors Size Type\n/dev/sdb1 2048 1050623 1048576 512M EFI System\n/dev/sdb2 1050624 60063710 59013087 28.1G Linux filesystem\n\nFilesystem/RAID signature on partition 1 will be wiped.\n",[709],{"type":20,"tag":45,"props":710,"children":711},{"__ignoreMap":7},[712,720,728,736,744,752,760,768,776,783,791,799,808,816],{"type":20,"tag":126,"props":713,"children":714},{"class":128,"line":129},[715],{"type":20,"tag":126,"props":716,"children":717},{},[718],{"type":25,"value":719},"Command (m for help): p\n",{"type":20,"tag":126,"props":721,"children":722},{"class":128,"line":265},[723],{"type":20,"tag":126,"props":724,"children":725},{},[726],{"type":25,"value":727},"Disk /dev/sdb: 28.66 GiB, 30752636928 bytes, 60063744 sectors\n",{"type":20,"tag":126,"props":729,"children":730},{"class":128,"line":274},[731],{"type":20,"tag":126,"props":732,"children":733},{},[734],{"type":25,"value":735},"Disk model: Ultra Fit\n",{"type":20,"tag":126,"props":737,"children":738},{"class":128,"line":284},[739],{"type":20,"tag":126,"props":740,"children":741},{},[742],{"type":25,"value":743},"Units: sectors of 1 * 512 = 512 bytes\n",{"type":20,"tag":126,"props":745,"children":746},{"class":128,"line":293},[747],{"type":20,"tag":126,"props":748,"children":749},{},[750],{"type":25,"value":751},"Sector size (logical/physical): 512 bytes / 512 bytes\n",{"type":20,"tag":126,"props":753,"children":754},{"class":128,"line":302},[755],{"type":20,"tag":126,"props":756,"children":757},{},[758],{"type":25,"value":759},"I/O size (minimum/optimal): 512 bytes / 512 bytes\n",{"type":20,"tag":126,"props":761,"children":762},{"class":128,"line":311},[763],{"type":20,"tag":126,"props":764,"children":765},{},[766],{"type":25,"value":767},"Disklabel type: gpt\n",{"type":20,"tag":126,"props":769,"children":770},{"class":128,"line":320},[771],{"type":20,"tag":126,"props":772,"children":773},{},[774],{"type":25,"value":775},"Disk identifier: E1D6C445-1B79-AB4D-A442-FA4AD6DF4ECC\n",{"type":20,"tag":126,"props":777,"children":778},{"class":128,"line":329},[779],{"type":20,"tag":126,"props":780,"children":781},{"emptyLinePlaceholder":278},[782],{"type":25,"value":281},{"type":20,"tag":126,"props":784,"children":785},{"class":128,"line":338},[786],{"type":20,"tag":126,"props":787,"children":788},{},[789],{"type":25,"value":790},"Device Start End Sectors Size Type\n",{"type":20,"tag":126,"props":792,"children":793},{"class":128,"line":347},[794],{"type":20,"tag":126,"props":795,"children":796},{},[797],{"type":25,"value":798},"/dev/sdb1 2048 1050623 1048576 512M EFI System\n",{"type":20,"tag":126,"props":800,"children":802},{"class":128,"line":801},12,[803],{"type":20,"tag":126,"props":804,"children":805},{},[806],{"type":25,"value":807},"/dev/sdb2 1050624 60063710 59013087 28.1G Linux filesystem\n",{"type":20,"tag":126,"props":809,"children":811},{"class":128,"line":810},13,[812],{"type":20,"tag":126,"props":813,"children":814},{"emptyLinePlaceholder":278},[815],{"type":25,"value":281},{"type":20,"tag":126,"props":817,"children":819},{"class":128,"line":818},14,[820],{"type":20,"tag":126,"props":821,"children":822},{},[823],{"type":25,"value":824},"Filesystem/RAID signature on partition 1 will be wiped.\n",{"type":20,"tag":675,"props":826,"children":828},{"id":827},"format-the-partitions",[829],{"type":25,"value":830},"Format the Partitions",{"type":20,"tag":21,"props":832,"children":833},{},[834,836],{"type":25,"value":835},"The UEFI specification mandates support for FAT file-systems, and FAT32 is\nrecommended for removable media. ",{"type":20,"tag":54,"props":837,"children":838},{},[839],{"type":20,"tag":58,"props":840,"children":843},{"href":841,"rel":842},"https://wiki.archlinux.org/index.php/EFI_system_partition#Format_the_partition",[62],[844],{"type":25,"value":845},"7",{"type":20,"tag":116,"props":847,"children":849},{"code":848,"language":119,"meta":7,"className":120,"style":7},"[root@archlinux ~]# pacman -Sy dosfstools\n[root@archlinux ~]# mkfs.fat -F32 /dev/sdb1\n",[850],{"type":20,"tag":45,"props":851,"children":852},{"__ignoreMap":7},[853,869],{"type":20,"tag":126,"props":854,"children":855},{"class":128,"line":129},[856,860,864],{"type":20,"tag":126,"props":857,"children":858},{"style":434},[859],{"type":25,"value":695},{"type":20,"tag":126,"props":861,"children":862},{"style":440},[863],{"type":25,"value":443},{"type":20,"tag":126,"props":865,"children":866},{"style":434},[867],{"type":25,"value":868},"]# pacman -Sy dosfstools\n",{"type":20,"tag":126,"props":870,"children":871},{"class":128,"line":265},[872,876,880],{"type":20,"tag":126,"props":873,"children":874},{"style":434},[875],{"type":25,"value":695},{"type":20,"tag":126,"props":877,"children":878},{"style":440},[879],{"type":25,"value":443},{"type":20,"tag":126,"props":881,"children":882},{"style":434},[883],{"type":25,"value":884},"]# mkfs.fat -F32 /dev/sdb1\n",{"type":20,"tag":21,"props":886,"children":887},{},[888,890,896,898],{"type":25,"value":889},"As for the root partition, it is recommended to use ",{"type":20,"tag":45,"props":891,"children":893},{"className":892},[],[894],{"type":25,"value":895},"ext4",{"type":25,"value":897}," without a journal to\nreduce the reads and writes to the file-system as this is detrimental to the\nflash-based USB drive. ",{"type":20,"tag":54,"props":899,"children":900},{},[901],{"type":20,"tag":58,"props":902,"children":905},{"href":903,"rel":904},"https://wiki.archlinux.org/index.php/Install_Arch_Linux_on_a_USB_key#Installation_tweaks",[62],[906],{"type":25,"value":907},"8",{"type":20,"tag":116,"props":909,"children":911},{"code":910,"language":119,"meta":7,"className":120,"style":7},"[root@archlinux ~]# mkfs.ext4 -O \"^has_journal\" /dev/sdb2\n",[912],{"type":20,"tag":45,"props":913,"children":914},{"__ignoreMap":7},[915],{"type":20,"tag":126,"props":916,"children":917},{"class":128,"line":129},[918,922,926,931,936],{"type":20,"tag":126,"props":919,"children":920},{"style":434},[921],{"type":25,"value":695},{"type":20,"tag":126,"props":923,"children":924},{"style":440},[925],{"type":25,"value":443},{"type":20,"tag":126,"props":927,"children":928},{"style":434},[929],{"type":25,"value":930},"]# mkfs.ext4 -O ",{"type":20,"tag":126,"props":932,"children":933},{"style":138},[934],{"type":25,"value":935},"\"^has_journal\"",{"type":20,"tag":126,"props":937,"children":938},{"style":434},[939],{"type":25,"value":940}," /dev/sdb2\n",{"type":20,"tag":675,"props":942,"children":944},{"id":943},"mount-the-partitions-and-bootstrap-the-environment",[945],{"type":25,"value":946},"Mount the Partitions and Bootstrap the Environment",{"type":20,"tag":116,"props":948,"children":950},{"code":949,"language":119,"meta":7,"className":120,"style":7},"[root@archlinux ~]# mount /dev/sdb2 /mnt\n[root@archlinux ~]# mkdir -p /mnt/boot/efi\n[root@archlinux ~]# mount /dev/sdb1 /mnt/boot/efi\n",[951],{"type":20,"tag":45,"props":952,"children":953},{"__ignoreMap":7},[954,970,986],{"type":20,"tag":126,"props":955,"children":956},{"class":128,"line":129},[957,961,965],{"type":20,"tag":126,"props":958,"children":959},{"style":434},[960],{"type":25,"value":695},{"type":20,"tag":126,"props":962,"children":963},{"style":440},[964],{"type":25,"value":443},{"type":20,"tag":126,"props":966,"children":967},{"style":434},[968],{"type":25,"value":969},"]# mount /dev/sdb2 /mnt\n",{"type":20,"tag":126,"props":971,"children":972},{"class":128,"line":265},[973,977,981],{"type":20,"tag":126,"props":974,"children":975},{"style":434},[976],{"type":25,"value":695},{"type":20,"tag":126,"props":978,"children":979},{"style":440},[980],{"type":25,"value":443},{"type":20,"tag":126,"props":982,"children":983},{"style":434},[984],{"type":25,"value":985},"]# mkdir -p /mnt/boot/efi\n",{"type":20,"tag":126,"props":987,"children":988},{"class":128,"line":274},[989,993,997],{"type":20,"tag":126,"props":990,"children":991},{"style":434},[992],{"type":25,"value":695},{"type":20,"tag":126,"props":994,"children":995},{"style":440},[996],{"type":25,"value":443},{"type":20,"tag":126,"props":998,"children":999},{"style":434},[1000],{"type":25,"value":1001},"]# mount /dev/sdb1 /mnt/boot/efi\n",{"type":20,"tag":116,"props":1003,"children":1005},{"code":1004,"language":119,"meta":7,"className":120,"style":7},"[root@archlinux ~]# pacman -S arch-install-scripts\n[root@archlinux ~]# pacstrap /mnt base linux linux-firmware\n[root@archlinux ~]# genfstab -U /mnt >> /mnt/etc/fstab\n",[1006],{"type":20,"tag":45,"props":1007,"children":1008},{"__ignoreMap":7},[1009,1025,1041],{"type":20,"tag":126,"props":1010,"children":1011},{"class":128,"line":129},[1012,1016,1020],{"type":20,"tag":126,"props":1013,"children":1014},{"style":434},[1015],{"type":25,"value":695},{"type":20,"tag":126,"props":1017,"children":1018},{"style":440},[1019],{"type":25,"value":443},{"type":20,"tag":126,"props":1021,"children":1022},{"style":434},[1023],{"type":25,"value":1024},"]# pacman -S arch-install-scripts\n",{"type":20,"tag":126,"props":1026,"children":1027},{"class":128,"line":265},[1028,1032,1036],{"type":20,"tag":126,"props":1029,"children":1030},{"style":434},[1031],{"type":25,"value":695},{"type":20,"tag":126,"props":1033,"children":1034},{"style":440},[1035],{"type":25,"value":443},{"type":20,"tag":126,"props":1037,"children":1038},{"style":434},[1039],{"type":25,"value":1040},"]# pacstrap /mnt base linux linux-firmware\n",{"type":20,"tag":126,"props":1042,"children":1043},{"class":128,"line":274},[1044,1048,1052,1057,1062],{"type":20,"tag":126,"props":1045,"children":1046},{"style":434},[1047],{"type":25,"value":695},{"type":20,"tag":126,"props":1049,"children":1050},{"style":440},[1051],{"type":25,"value":443},{"type":20,"tag":126,"props":1053,"children":1054},{"style":434},[1055],{"type":25,"value":1056},"]# genfstab -U /mnt ",{"type":20,"tag":126,"props":1058,"children":1059},{"style":440},[1060],{"type":25,"value":1061},">>",{"type":20,"tag":126,"props":1063,"children":1064},{"style":434},[1065],{"type":25,"value":1066}," /mnt/etc/fstab\n",{"type":20,"tag":675,"props":1068,"children":1070},{"id":1069},"configure-the-new-environment",[1071],{"type":25,"value":1072},"Configure the New Environment",{"type":20,"tag":116,"props":1074,"children":1076},{"code":1075},"[root@archlinux ~]# arch-chroot /mnt\n",[1077],{"type":20,"tag":45,"props":1078,"children":1079},{"__ignoreMap":7},[1080],{"type":25,"value":1075},{"type":20,"tag":116,"props":1082,"children":1084},{"code":1083},"[root@archlinux /]# ln -sf /usr/share/zoneinfo/US/Eastern /etc/localtime\n[root@archlinux /]# hwclock --systohc\n[root@archlinux /]# sed -i 's/#en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen\n[root@archlinux /]# locale-gen\n[root@archlinux /]# echo \"LANG=en_US.UTF-8\" > /etc/locale.conf\n",[1085],{"type":20,"tag":45,"props":1086,"children":1087},{"__ignoreMap":7},[1088],{"type":25,"value":1083},{"type":20,"tag":116,"props":1090,"children":1092},{"code":1091},"[root@archlinux /]# hostnamectl set-hostname usb\n[root@archlinux /]# echo \"127.0.0.1 localhost\" >> /etc/hosts\n[root@archlinux /]# echo \"::1 localhost\" >> /etc/hosts\n",[1093],{"type":20,"tag":45,"props":1094,"children":1095},{"__ignoreMap":7},[1096],{"type":25,"value":1091},{"type":20,"tag":21,"props":1098,"children":1099},{},[1100,1102,1108,1110],{"type":25,"value":1101},"Note, one difference here from a standard installation is that the\n",{"type":20,"tag":45,"props":1103,"children":1105},{"className":1104},[],[1106],{"type":25,"value":1107},"--removable",{"type":25,"value":1109}," flag is specified when installing the GRUB bootloader.\n",{"type":20,"tag":54,"props":1111,"children":1112},{},[1113],{"type":20,"tag":58,"props":1114,"children":1117},{"href":1115,"rel":1116},"https://wiki.archlinux.org/index.php/GRUB#UEFI_systems",[62],[1118],{"type":25,"value":1119},"10",{"type":20,"tag":116,"props":1121,"children":1123},{"code":1122},"[root@archlinux /]# pacman -S grub\n[root@archlinux /]# grub-install --target=x86_64-efi --efi-directory=/boot/efi --removable --recheck\n[root@usb /]# grub-mkconfig -o /boot/grub/grub.cfg\n",[1124],{"type":20,"tag":45,"props":1125,"children":1126},{"__ignoreMap":7},[1127],{"type":25,"value":1122},{"type":20,"tag":21,"props":1129,"children":1130},{},[1131],{"type":25,"value":1132},"Shutdown the virtual machine, restart the host machine, and boot the newly\ncreated Arch Linux thumb-drive!",{"type":20,"tag":21,"props":1134,"children":1135},{},[1136],{"type":25,"value":1137},"🎉",{"type":20,"tag":92,"props":1139,"children":1141},{"id":1140},"side-note",[1142],{"type":25,"value":1143},"Side-note",{"type":20,"tag":21,"props":1145,"children":1146},{},[1147,1149,1155,1157,1162,1164],{"type":25,"value":1148},"It was attempted to use the ",{"type":20,"tag":45,"props":1150,"children":1152},{"className":1151},[],[1153],{"type":25,"value":1154},"controlvm usbattach",{"type":25,"value":1156}," command to pass the USB\ndevice to the guest machine, but this did not work as it expects the virtual\nmachine to already be running, and the ",{"type":20,"tag":45,"props":1158,"children":1160},{"className":1159},[],[1161],{"type":25,"value":236},{"type":25,"value":1163}," option runs prior to\nbooting the machine. ",{"type":20,"tag":54,"props":1165,"children":1166},{},[1167],{"type":20,"tag":58,"props":1168,"children":1171},{"href":1169,"rel":1170},"https://www.vagrantup.com/docs/virtualbox/configuration.html#vboxmanage-customizations",[62],[1172],{"type":25,"value":1173},"11",{"type":20,"tag":116,"props":1175,"children":1177},{"code":1176,"language":249,"meta":7,"className":250,"style":7},"Command: [\"controlvm\", \"060a716b-1965-49e2-bc56-12beed5df716\", \"usbattach36fc9e60-c465-11cf-8056-444553540000\"]\n\nStderr: VBoxManage.exe: error: Machine '060a716b-1965-49e2-bc56-12beed5df716' is not currently running.\n",[1178],{"type":20,"tag":45,"props":1179,"children":1180},{"__ignoreMap":7},[1181,1189,1196],{"type":20,"tag":126,"props":1182,"children":1183},{"class":128,"line":129},[1184],{"type":20,"tag":126,"props":1185,"children":1186},{},[1187],{"type":25,"value":1188},"Command: [\"controlvm\", \"060a716b-1965-49e2-bc56-12beed5df716\", \"usbattach36fc9e60-c465-11cf-8056-444553540000\"]\n",{"type":20,"tag":126,"props":1190,"children":1191},{"class":128,"line":265},[1192],{"type":20,"tag":126,"props":1193,"children":1194},{"emptyLinePlaceholder":278},[1195],{"type":25,"value":281},{"type":20,"tag":126,"props":1197,"children":1198},{"class":128,"line":274},[1199],{"type":20,"tag":126,"props":1200,"children":1201},{},[1202],{"type":25,"value":1203},"Stderr: VBoxManage.exe: error: Machine '060a716b-1965-49e2-bc56-12beed5df716' is not currently running.\n",{"type":20,"tag":92,"props":1205,"children":1207},{"id":1206},"references",[1208],{"type":25,"value":1209},"References",{"type":20,"tag":1211,"props":1212,"children":1213},"ol",{},[1214,1224,1233,1242,1251,1260,1269,1278,1287,1296,1305],{"type":20,"tag":1215,"props":1216,"children":1217},"li",{},[1218],{"type":20,"tag":58,"props":1219,"children":1221},{"href":60,"rel":1220},[62],[1222],{"type":25,"value":1223},"Docker Desktop on Mac vs. Docker Toolbox",{"type":20,"tag":1215,"props":1225,"children":1226},{},[1227],{"type":20,"tag":58,"props":1228,"children":1230},{"href":70,"rel":1229},[62],[1231],{"type":25,"value":1232},"GitHub - HyperKit",{"type":20,"tag":1215,"props":1234,"children":1235},{},[1236],{"type":20,"tag":58,"props":1237,"children":1239},{"href":78,"rel":1238},[62],[1240],{"type":25,"value":1241},"GitHub - Docker for Mac - Issue #900",{"type":20,"tag":1215,"props":1243,"children":1244},{},[1245],{"type":20,"tag":58,"props":1246,"children":1248},{"href":108,"rel":1247},[62],[1249],{"type":25,"value":1250},"Vagrant Cloud - Arch Linux",{"type":20,"tag":1215,"props":1252,"children":1253},{},[1254],{"type":20,"tag":58,"props":1255,"children":1257},{"href":216,"rel":1256},[62],[1258],{"type":25,"value":1259},"Attaching USB Devices to VirtualBox Guests using VBoxManage",{"type":20,"tag":1215,"props":1261,"children":1262},{},[1263],{"type":20,"tag":58,"props":1264,"children":1266},{"href":224,"rel":1265},[62],[1267],{"type":25,"value":1268},"GitHub Gist - Vagrant USB Filter",{"type":20,"tag":1215,"props":1270,"children":1271},{},[1272],{"type":20,"tag":58,"props":1273,"children":1275},{"href":841,"rel":1274},[62],[1276],{"type":25,"value":1277},"Arch Linux Wiki - EFI System Partition - Format Partitions",{"type":20,"tag":1215,"props":1279,"children":1280},{},[1281],{"type":20,"tag":58,"props":1282,"children":1284},{"href":903,"rel":1283},[62],[1285],{"type":25,"value":1286},"Arch Linux Wiki - Arch Linux on USB - Installation Tweaks",{"type":20,"tag":1215,"props":1288,"children":1289},{},[1290],{"type":20,"tag":58,"props":1291,"children":1293},{"href":667,"rel":1292},[62],[1294],{"type":25,"value":1295},"Arch Linux Wiki - Installation Guide",{"type":20,"tag":1215,"props":1297,"children":1298},{},[1299],{"type":20,"tag":58,"props":1300,"children":1302},{"href":1115,"rel":1301},[62],[1303],{"type":25,"value":1304},"Arch Linux Wiki - GRUB - UEFI Systems",{"type":20,"tag":1215,"props":1306,"children":1307},{},[1308],{"type":20,"tag":58,"props":1309,"children":1311},{"href":1169,"rel":1310},[62],[1312],{"type":25,"value":1313},"Vagrant VBoxManage Customizations ",{"type":20,"tag":1315,"props":1316,"children":1317},"style",{},[1318],{"type":25,"value":1319},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":265,"depth":265,"links":1321},[1322,1323,1329,1330],{"id":94,"depth":265,"text":97},{"id":656,"depth":265,"text":659,"children":1324},[1325,1326,1327,1328],{"id":677,"depth":274,"text":680},{"id":827,"depth":274,"text":830},{"id":943,"depth":274,"text":946},{"id":1069,"depth":274,"text":1072},{"id":1140,"depth":265,"text":1143},{"id":1206,"depth":265,"text":1209},"markdown","content:articles:persistent-archlinux-usb.md","content","articles/persistent-archlinux-usb.md","articles/persistent-archlinux-usb","md",1726174739528] \ No newline at end of file +[{"data":1,"prerenderedAt":1336},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"draft":6,"tags":11,"categories":14,"excerpt":16,"body":26,"_type":1331,"_id":1332,"_source":1333,"_file":1334,"_extension":1335},"/articles/persistent-archlinux-usb","articles",false,"","Create a Persistent Arch Linux Bootable USB with Vagrant","When installing a linux distribution, it is common for the instructions to have\nthe user create a bootable USB, boot from the device, and proceed with the\ninstallation procedure from that live medium. However, this blog post will\noutline an alternative approach where a virtual machine created with Vagrant\nwill be used in favor of the live medium.","2020-01-09",[12,13],"vagrant","archlinux",[15],"linux",{"type":17,"children":18},"root",[19],{"type":20,"tag":21,"props":22,"children":23},"element","p",{},[24],{"type":25,"value":9},"text",{"type":17,"children":27,"toc":1320},[28,32,39,85,91,98,115,152,165,190,246,354,367,388,654,660,674,681,705,825,831,846,885,908,941,947,1002,1067,1073,1081,1089,1097,1120,1128,1133,1138,1144,1174,1204,1210,1314],{"type":20,"tag":21,"props":29,"children":30},{},[31],{"type":25,"value":9},{"type":20,"tag":33,"props":34,"children":36},"h1",{"id":35},"preface",[37],{"type":25,"value":38},"Preface",{"type":20,"tag":21,"props":40,"children":41},{},[42,44,51,53,83],{"type":25,"value":43},"The original intention was to use Docker for this process -- leveraging the\n",{"type":20,"tag":45,"props":46,"children":48},"code",{"className":47},[],[49],{"type":25,"value":50},"--device",{"type":25,"value":52}," flag and mounting the target USB device in the Docker container,\nbut the underlying hypervisor in Docker Desktop for Mac does not support this.\n",{"type":20,"tag":54,"props":55,"children":56},"sup",{},[57,66,68,75,76],{"type":20,"tag":58,"props":59,"children":63},"a",{"href":60,"rel":61},"https://docs.docker.com/docker-for-mac/docker-toolbox/",[62],"nofollow",[64],{"type":25,"value":65},"1",{"type":25,"value":67}," ",{"type":20,"tag":58,"props":69,"children":72},{"href":70,"rel":71},"https://github.com/moby/hyperkit",[62],[73],{"type":25,"value":74},"2",{"type":25,"value":67},{"type":20,"tag":58,"props":77,"children":80},{"href":78,"rel":79},"https://github.com/docker/for-mac/issues/900",[62],[81],{"type":25,"value":82},"3",{"type":25,"value":84}," While there are workarounds using Docker\nMachine, Vagrant felt like the path of least resistance.",{"type":20,"tag":33,"props":86,"children":88},{"id":87},"instructions",[89],{"type":25,"value":90},"Instructions",{"type":20,"tag":92,"props":93,"children":95},"h2",{"id":94},"create-an-arch-linux-virtual-machine-with-vagrant",[96],{"type":25,"value":97},"Create an Arch Linux Virtual Machine with Vagrant",{"type":20,"tag":21,"props":99,"children":100},{},[101,103,113],{"type":25,"value":102},"Get the latest Arch Linux image ",{"type":20,"tag":54,"props":104,"children":105},{},[106],{"type":20,"tag":58,"props":107,"children":110},{"href":108,"rel":109},"https://app.vagrantup.com/archlinux/boxes/archlinux",[62],[111],{"type":25,"value":112},"4",{"type":25,"value":114}," from the Vagrant Cloud Box\nCatalog.",{"type":20,"tag":116,"props":117,"children":121},"pre",{"code":118,"language":119,"meta":7,"className":120,"style":7},"vagrant box add archlinux/archlinux\n","bash","language-bash shiki shiki-themes github-light",[122],{"type":20,"tag":45,"props":123,"children":124},{"__ignoreMap":7},[125],{"type":20,"tag":126,"props":127,"children":130},"span",{"class":128,"line":129},"line",1,[131,136,142,147],{"type":20,"tag":126,"props":132,"children":134},{"style":133},"--shiki-default:#6F42C1",[135],{"type":25,"value":12},{"type":20,"tag":126,"props":137,"children":139},{"style":138},"--shiki-default:#032F62",[140],{"type":25,"value":141}," box",{"type":20,"tag":126,"props":143,"children":144},{"style":138},[145],{"type":25,"value":146}," add",{"type":20,"tag":126,"props":148,"children":149},{"style":138},[150],{"type":25,"value":151}," archlinux/archlinux\n",{"type":20,"tag":21,"props":153,"children":154},{},[155,157,163],{"type":25,"value":156},"Determine the USB vendor information for the thumb-drive that we will\npass-through to the virtual machine. Using the ",{"type":20,"tag":45,"props":158,"children":160},{"className":159},[],[161],{"type":25,"value":162},"VBoxManage",{"type":25,"value":164}," utility that comes\nwith Virtual Box, list the devices, and make note of the Vendor and Product ID.",{"type":20,"tag":116,"props":166,"children":168},{"code":167,"language":119,"meta":7,"className":120,"style":7}," VBoxManage list usbhost\n",[169],{"type":20,"tag":45,"props":170,"children":171},{"__ignoreMap":7},[172],{"type":20,"tag":126,"props":173,"children":174},{"class":128,"line":129},[175,180,185],{"type":20,"tag":126,"props":176,"children":177},{"style":133},[178],{"type":25,"value":179}," VBoxManage",{"type":20,"tag":126,"props":181,"children":182},{"style":138},[183],{"type":25,"value":184}," list",{"type":20,"tag":126,"props":186,"children":187},{"style":138},[188],{"type":25,"value":189}," usbhost\n",{"type":20,"tag":21,"props":191,"children":192},{},[193,195,201,203,209,211,229,231,237,239,244],{"type":25,"value":194},"Create a ",{"type":20,"tag":45,"props":196,"children":198},{"className":197},[],[199],{"type":25,"value":200},"Vagrantfile",{"type":25,"value":202}," with ",{"type":20,"tag":45,"props":204,"children":206},{"className":205},[],[207],{"type":25,"value":208},"archlinx/archlinux",{"type":25,"value":210}," as the target box, and the USB\ndevice information that is passed through. ",{"type":20,"tag":54,"props":212,"children":213},{},[214,221,222],{"type":20,"tag":58,"props":215,"children":218},{"href":216,"rel":217},"https://antonyjepson.wordpress.com/2012/01/26/quickly-attaching-usb-devices-to-virtualbox-guests-using-vboxmanage/",[62],[219],{"type":25,"value":220},"5",{"type":25,"value":67},{"type":20,"tag":58,"props":223,"children":226},{"href":224,"rel":225},"https://gist.github.com/dscape/7d829c0c116ef419f963",[62],[227],{"type":25,"value":228},"6",{"type":25,"value":230}," Vagrant\noffers a handy customization parameter ",{"type":20,"tag":45,"props":232,"children":234},{"className":233},[],[235],{"type":25,"value":236},"vb.customize",{"type":25,"value":238}," that calls the\n",{"type":20,"tag":45,"props":240,"children":242},{"className":241},[],[243],{"type":25,"value":162},{"type":25,"value":245}," command under-the-hood, allowing one to enable the guest machine\nto access the host machine's USB devices.",{"type":20,"tag":116,"props":247,"children":251},{"code":248,"language":249,"meta":7,"className":250,"style":7},"# -*- mode: ruby -*-\n# vi: set ft=ruby :\n\nVagrant.configure(\"2\") do |config|\n config.vm.box = \"archlinux/archlinux\"\n config.vm.provider \"virtualbox\" do |vb|\n vb.name = \"archlinux\"\n vb.customize ['modifyvm', :id, '--usb', 'on']\n vb.customize ['usbfilter', 'add', '1', '--target', :id, '--name', 'SanDisk Ultra Fit', '--vendorid', '0x0781', '--productid', '0x5583']\n end\nend\n","txt","language-txt shiki shiki-themes github-light",[252],{"type":20,"tag":45,"props":253,"children":254},{"__ignoreMap":7},[255,263,272,282,291,300,309,318,327,336,345],{"type":20,"tag":126,"props":256,"children":257},{"class":128,"line":129},[258],{"type":20,"tag":126,"props":259,"children":260},{},[261],{"type":25,"value":262},"# -*- mode: ruby -*-\n",{"type":20,"tag":126,"props":264,"children":266},{"class":128,"line":265},2,[267],{"type":20,"tag":126,"props":268,"children":269},{},[270],{"type":25,"value":271},"# vi: set ft=ruby :\n",{"type":20,"tag":126,"props":273,"children":275},{"class":128,"line":274},3,[276],{"type":20,"tag":126,"props":277,"children":279},{"emptyLinePlaceholder":278},true,[280],{"type":25,"value":281},"\n",{"type":20,"tag":126,"props":283,"children":285},{"class":128,"line":284},4,[286],{"type":20,"tag":126,"props":287,"children":288},{},[289],{"type":25,"value":290},"Vagrant.configure(\"2\") do |config|\n",{"type":20,"tag":126,"props":292,"children":294},{"class":128,"line":293},5,[295],{"type":20,"tag":126,"props":296,"children":297},{},[298],{"type":25,"value":299}," config.vm.box = \"archlinux/archlinux\"\n",{"type":20,"tag":126,"props":301,"children":303},{"class":128,"line":302},6,[304],{"type":20,"tag":126,"props":305,"children":306},{},[307],{"type":25,"value":308}," config.vm.provider \"virtualbox\" do |vb|\n",{"type":20,"tag":126,"props":310,"children":312},{"class":128,"line":311},7,[313],{"type":20,"tag":126,"props":314,"children":315},{},[316],{"type":25,"value":317}," vb.name = \"archlinux\"\n",{"type":20,"tag":126,"props":319,"children":321},{"class":128,"line":320},8,[322],{"type":20,"tag":126,"props":323,"children":324},{},[325],{"type":25,"value":326}," vb.customize ['modifyvm', :id, '--usb', 'on']\n",{"type":20,"tag":126,"props":328,"children":330},{"class":128,"line":329},9,[331],{"type":20,"tag":126,"props":332,"children":333},{},[334],{"type":25,"value":335}," vb.customize ['usbfilter', 'add', '1', '--target', :id, '--name', 'SanDisk Ultra Fit', '--vendorid', '0x0781', '--productid', '0x5583']\n",{"type":20,"tag":126,"props":337,"children":339},{"class":128,"line":338},10,[340],{"type":20,"tag":126,"props":341,"children":342},{},[343],{"type":25,"value":344}," end\n",{"type":20,"tag":126,"props":346,"children":348},{"class":128,"line":347},11,[349],{"type":20,"tag":126,"props":350,"children":351},{},[352],{"type":25,"value":353},"end\n",{"type":20,"tag":21,"props":355,"children":356},{},[357,359,365],{"type":25,"value":358},"When virtual machine is brought up, the ",{"type":20,"tag":45,"props":360,"children":362},{"className":361},[],[363],{"type":25,"value":364},"usbfilter",{"type":25,"value":366}," is applied, and the guest\nis able to access to the host machine's USB device that was specified in the\nfilter.",{"type":20,"tag":21,"props":368,"children":369},{},[370,372,378,380,386],{"type":25,"value":371},"Start the machine, ",{"type":20,"tag":45,"props":373,"children":375},{"className":374},[],[376],{"type":25,"value":377},"ssh",{"type":25,"value":379}," into the guest, and list the devices to confirm that\nthe USB device is available (see: ",{"type":20,"tag":45,"props":381,"children":383},{"className":382},[],[384],{"type":25,"value":385},"/dev/sdb",{"type":25,"value":387},").",{"type":20,"tag":116,"props":389,"children":391},{"code":390,"language":119,"meta":7,"className":120,"style":7},"$ vagrant up\n$ vagrant ssh\n[vagrant@archlinux ~]$ lsblk\nNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT\nsda 8:0 0 20G 0 disk\n├─sda1 8:1 0 1.9G 0 part [SWAP]\n└─sda2 8:2 0 18.1G 0 part /\nsdb 8:16 1 28.7G 0 disk\n└─sdb1 8:17 1 8G 0 part\n",[392],{"type":20,"tag":45,"props":393,"children":394},{"__ignoreMap":7},[395,413,429,449,487,521,557,592,623],{"type":20,"tag":126,"props":396,"children":397},{"class":128,"line":129},[398,403,408],{"type":20,"tag":126,"props":399,"children":400},{"style":133},[401],{"type":25,"value":402},"$",{"type":20,"tag":126,"props":404,"children":405},{"style":138},[406],{"type":25,"value":407}," vagrant",{"type":20,"tag":126,"props":409,"children":410},{"style":138},[411],{"type":25,"value":412}," up\n",{"type":20,"tag":126,"props":414,"children":415},{"class":128,"line":265},[416,420,424],{"type":20,"tag":126,"props":417,"children":418},{"style":133},[419],{"type":25,"value":402},{"type":20,"tag":126,"props":421,"children":422},{"style":138},[423],{"type":25,"value":407},{"type":20,"tag":126,"props":425,"children":426},{"style":138},[427],{"type":25,"value":428}," ssh\n",{"type":20,"tag":126,"props":430,"children":431},{"class":128,"line":274},[432,438,444],{"type":20,"tag":126,"props":433,"children":435},{"style":434},"--shiki-default:#24292E",[436],{"type":25,"value":437},"[vagrant@archlinux ",{"type":20,"tag":126,"props":439,"children":441},{"style":440},"--shiki-default:#D73A49",[442],{"type":25,"value":443},"~",{"type":20,"tag":126,"props":445,"children":446},{"style":434},[447],{"type":25,"value":448},"]$ lsblk\n",{"type":20,"tag":126,"props":450,"children":451},{"class":128,"line":284},[452,457,462,467,472,477,482],{"type":20,"tag":126,"props":453,"children":454},{"style":133},[455],{"type":25,"value":456},"NAME",{"type":20,"tag":126,"props":458,"children":459},{"style":138},[460],{"type":25,"value":461}," MAJ:MIN",{"type":20,"tag":126,"props":463,"children":464},{"style":138},[465],{"type":25,"value":466}," RM",{"type":20,"tag":126,"props":468,"children":469},{"style":138},[470],{"type":25,"value":471}," SIZE",{"type":20,"tag":126,"props":473,"children":474},{"style":138},[475],{"type":25,"value":476}," RO",{"type":20,"tag":126,"props":478,"children":479},{"style":138},[480],{"type":25,"value":481}," TYPE",{"type":20,"tag":126,"props":483,"children":484},{"style":138},[485],{"type":25,"value":486}," MOUNTPOINT\n",{"type":20,"tag":126,"props":488,"children":489},{"class":128,"line":293},[490,495,500,506,511,516],{"type":20,"tag":126,"props":491,"children":492},{"style":133},[493],{"type":25,"value":494},"sda",{"type":20,"tag":126,"props":496,"children":497},{"style":138},[498],{"type":25,"value":499}," 8:0",{"type":20,"tag":126,"props":501,"children":503},{"style":502},"--shiki-default:#005CC5",[504],{"type":25,"value":505}," 0",{"type":20,"tag":126,"props":507,"children":508},{"style":138},[509],{"type":25,"value":510}," 20G",{"type":20,"tag":126,"props":512,"children":513},{"style":502},[514],{"type":25,"value":515}," 0",{"type":20,"tag":126,"props":517,"children":518},{"style":138},[519],{"type":25,"value":520}," disk\n",{"type":20,"tag":126,"props":522,"children":523},{"class":128,"line":302},[524,529,534,538,543,547,552],{"type":20,"tag":126,"props":525,"children":526},{"style":133},[527],{"type":25,"value":528},"├─sda1",{"type":20,"tag":126,"props":530,"children":531},{"style":138},[532],{"type":25,"value":533}," 8:1",{"type":20,"tag":126,"props":535,"children":536},{"style":502},[537],{"type":25,"value":505},{"type":20,"tag":126,"props":539,"children":540},{"style":138},[541],{"type":25,"value":542}," 1.9G",{"type":20,"tag":126,"props":544,"children":545},{"style":502},[546],{"type":25,"value":515},{"type":20,"tag":126,"props":548,"children":549},{"style":138},[550],{"type":25,"value":551}," part",{"type":20,"tag":126,"props":553,"children":554},{"style":434},[555],{"type":25,"value":556}," [SWAP]\n",{"type":20,"tag":126,"props":558,"children":559},{"class":128,"line":311},[560,565,570,574,579,583,587],{"type":20,"tag":126,"props":561,"children":562},{"style":133},[563],{"type":25,"value":564},"└─sda2",{"type":20,"tag":126,"props":566,"children":567},{"style":138},[568],{"type":25,"value":569}," 8:2",{"type":20,"tag":126,"props":571,"children":572},{"style":502},[573],{"type":25,"value":505},{"type":20,"tag":126,"props":575,"children":576},{"style":138},[577],{"type":25,"value":578}," 18.1G",{"type":20,"tag":126,"props":580,"children":581},{"style":502},[582],{"type":25,"value":515},{"type":20,"tag":126,"props":584,"children":585},{"style":138},[586],{"type":25,"value":551},{"type":20,"tag":126,"props":588,"children":589},{"style":138},[590],{"type":25,"value":591}," /\n",{"type":20,"tag":126,"props":593,"children":594},{"class":128,"line":320},[595,600,605,610,615,619],{"type":20,"tag":126,"props":596,"children":597},{"style":133},[598],{"type":25,"value":599},"sdb",{"type":20,"tag":126,"props":601,"children":602},{"style":138},[603],{"type":25,"value":604}," 8:16",{"type":20,"tag":126,"props":606,"children":607},{"style":502},[608],{"type":25,"value":609}," 1",{"type":20,"tag":126,"props":611,"children":612},{"style":138},[613],{"type":25,"value":614}," 28.7G",{"type":20,"tag":126,"props":616,"children":617},{"style":502},[618],{"type":25,"value":515},{"type":20,"tag":126,"props":620,"children":621},{"style":138},[622],{"type":25,"value":520},{"type":20,"tag":126,"props":624,"children":625},{"class":128,"line":329},[626,631,636,640,645,649],{"type":20,"tag":126,"props":627,"children":628},{"style":133},[629],{"type":25,"value":630},"└─sdb1",{"type":20,"tag":126,"props":632,"children":633},{"style":138},[634],{"type":25,"value":635}," 8:17",{"type":20,"tag":126,"props":637,"children":638},{"style":502},[639],{"type":25,"value":609},{"type":20,"tag":126,"props":641,"children":642},{"style":138},[643],{"type":25,"value":644}," 8G",{"type":20,"tag":126,"props":646,"children":647},{"style":502},[648],{"type":25,"value":515},{"type":20,"tag":126,"props":650,"children":651},{"style":138},[652],{"type":25,"value":653}," part\n",{"type":20,"tag":92,"props":655,"children":657},{"id":656},"install-arch-linux-on-the-usb-drive",[658],{"type":25,"value":659},"Install Arch Linux on the USB Drive",{"type":20,"tag":21,"props":661,"children":662},{},[663,665,672],{"type":25,"value":664},"The ",{"type":20,"tag":58,"props":666,"children":669},{"href":667,"rel":668},"https://wiki.archlinux.org/index.php/Installation_guide",[62],[670],{"type":25,"value":671},"Arch Linux Installation Guide",{"type":25,"value":673}," outlines the installation procedure in\ngreat detail -- the following steps follow this closely with a few alteration\ndue to installing onto removable media.",{"type":20,"tag":675,"props":676,"children":678},"h3",{"id":677},"partition-the-disk-uefi-with-gpt",[679],{"type":25,"value":680},"Partition the Disk (UEFI with GPT)",{"type":20,"tag":116,"props":682,"children":684},{"code":683,"language":119,"meta":7,"className":120,"style":7},"[root@archlinux ~]# fdisk /dev/sdb\n",[685],{"type":20,"tag":45,"props":686,"children":687},{"__ignoreMap":7},[688],{"type":20,"tag":126,"props":689,"children":690},{"class":128,"line":129},[691,696,700],{"type":20,"tag":126,"props":692,"children":693},{"style":434},[694],{"type":25,"value":695},"[root@archlinux ",{"type":20,"tag":126,"props":697,"children":698},{"style":440},[699],{"type":25,"value":443},{"type":20,"tag":126,"props":701,"children":702},{"style":434},[703],{"type":25,"value":704},"]# fdisk /dev/sdb\n",{"type":20,"tag":116,"props":706,"children":708},{"code":707,"language":249,"meta":7,"className":250,"style":7},"Command (m for help): p\nDisk /dev/sdb: 28.66 GiB, 30752636928 bytes, 60063744 sectors\nDisk model: Ultra Fit\nUnits: sectors of 1 * 512 = 512 bytes\nSector size (logical/physical): 512 bytes / 512 bytes\nI/O size (minimum/optimal): 512 bytes / 512 bytes\nDisklabel type: gpt\nDisk identifier: E1D6C445-1B79-AB4D-A442-FA4AD6DF4ECC\n\nDevice Start End Sectors Size Type\n/dev/sdb1 2048 1050623 1048576 512M EFI System\n/dev/sdb2 1050624 60063710 59013087 28.1G Linux filesystem\n\nFilesystem/RAID signature on partition 1 will be wiped.\n",[709],{"type":20,"tag":45,"props":710,"children":711},{"__ignoreMap":7},[712,720,728,736,744,752,760,768,776,783,791,799,808,816],{"type":20,"tag":126,"props":713,"children":714},{"class":128,"line":129},[715],{"type":20,"tag":126,"props":716,"children":717},{},[718],{"type":25,"value":719},"Command (m for help): p\n",{"type":20,"tag":126,"props":721,"children":722},{"class":128,"line":265},[723],{"type":20,"tag":126,"props":724,"children":725},{},[726],{"type":25,"value":727},"Disk /dev/sdb: 28.66 GiB, 30752636928 bytes, 60063744 sectors\n",{"type":20,"tag":126,"props":729,"children":730},{"class":128,"line":274},[731],{"type":20,"tag":126,"props":732,"children":733},{},[734],{"type":25,"value":735},"Disk model: Ultra Fit\n",{"type":20,"tag":126,"props":737,"children":738},{"class":128,"line":284},[739],{"type":20,"tag":126,"props":740,"children":741},{},[742],{"type":25,"value":743},"Units: sectors of 1 * 512 = 512 bytes\n",{"type":20,"tag":126,"props":745,"children":746},{"class":128,"line":293},[747],{"type":20,"tag":126,"props":748,"children":749},{},[750],{"type":25,"value":751},"Sector size (logical/physical): 512 bytes / 512 bytes\n",{"type":20,"tag":126,"props":753,"children":754},{"class":128,"line":302},[755],{"type":20,"tag":126,"props":756,"children":757},{},[758],{"type":25,"value":759},"I/O size (minimum/optimal): 512 bytes / 512 bytes\n",{"type":20,"tag":126,"props":761,"children":762},{"class":128,"line":311},[763],{"type":20,"tag":126,"props":764,"children":765},{},[766],{"type":25,"value":767},"Disklabel type: gpt\n",{"type":20,"tag":126,"props":769,"children":770},{"class":128,"line":320},[771],{"type":20,"tag":126,"props":772,"children":773},{},[774],{"type":25,"value":775},"Disk identifier: E1D6C445-1B79-AB4D-A442-FA4AD6DF4ECC\n",{"type":20,"tag":126,"props":777,"children":778},{"class":128,"line":329},[779],{"type":20,"tag":126,"props":780,"children":781},{"emptyLinePlaceholder":278},[782],{"type":25,"value":281},{"type":20,"tag":126,"props":784,"children":785},{"class":128,"line":338},[786],{"type":20,"tag":126,"props":787,"children":788},{},[789],{"type":25,"value":790},"Device Start End Sectors Size Type\n",{"type":20,"tag":126,"props":792,"children":793},{"class":128,"line":347},[794],{"type":20,"tag":126,"props":795,"children":796},{},[797],{"type":25,"value":798},"/dev/sdb1 2048 1050623 1048576 512M EFI System\n",{"type":20,"tag":126,"props":800,"children":802},{"class":128,"line":801},12,[803],{"type":20,"tag":126,"props":804,"children":805},{},[806],{"type":25,"value":807},"/dev/sdb2 1050624 60063710 59013087 28.1G Linux filesystem\n",{"type":20,"tag":126,"props":809,"children":811},{"class":128,"line":810},13,[812],{"type":20,"tag":126,"props":813,"children":814},{"emptyLinePlaceholder":278},[815],{"type":25,"value":281},{"type":20,"tag":126,"props":817,"children":819},{"class":128,"line":818},14,[820],{"type":20,"tag":126,"props":821,"children":822},{},[823],{"type":25,"value":824},"Filesystem/RAID signature on partition 1 will be wiped.\n",{"type":20,"tag":675,"props":826,"children":828},{"id":827},"format-the-partitions",[829],{"type":25,"value":830},"Format the Partitions",{"type":20,"tag":21,"props":832,"children":833},{},[834,836],{"type":25,"value":835},"The UEFI specification mandates support for FAT file-systems, and FAT32 is\nrecommended for removable media. ",{"type":20,"tag":54,"props":837,"children":838},{},[839],{"type":20,"tag":58,"props":840,"children":843},{"href":841,"rel":842},"https://wiki.archlinux.org/index.php/EFI_system_partition#Format_the_partition",[62],[844],{"type":25,"value":845},"7",{"type":20,"tag":116,"props":847,"children":849},{"code":848,"language":119,"meta":7,"className":120,"style":7},"[root@archlinux ~]# pacman -Sy dosfstools\n[root@archlinux ~]# mkfs.fat -F32 /dev/sdb1\n",[850],{"type":20,"tag":45,"props":851,"children":852},{"__ignoreMap":7},[853,869],{"type":20,"tag":126,"props":854,"children":855},{"class":128,"line":129},[856,860,864],{"type":20,"tag":126,"props":857,"children":858},{"style":434},[859],{"type":25,"value":695},{"type":20,"tag":126,"props":861,"children":862},{"style":440},[863],{"type":25,"value":443},{"type":20,"tag":126,"props":865,"children":866},{"style":434},[867],{"type":25,"value":868},"]# pacman -Sy dosfstools\n",{"type":20,"tag":126,"props":870,"children":871},{"class":128,"line":265},[872,876,880],{"type":20,"tag":126,"props":873,"children":874},{"style":434},[875],{"type":25,"value":695},{"type":20,"tag":126,"props":877,"children":878},{"style":440},[879],{"type":25,"value":443},{"type":20,"tag":126,"props":881,"children":882},{"style":434},[883],{"type":25,"value":884},"]# mkfs.fat -F32 /dev/sdb1\n",{"type":20,"tag":21,"props":886,"children":887},{},[888,890,896,898],{"type":25,"value":889},"As for the root partition, it is recommended to use ",{"type":20,"tag":45,"props":891,"children":893},{"className":892},[],[894],{"type":25,"value":895},"ext4",{"type":25,"value":897}," without a journal to\nreduce the reads and writes to the file-system as this is detrimental to the\nflash-based USB drive. ",{"type":20,"tag":54,"props":899,"children":900},{},[901],{"type":20,"tag":58,"props":902,"children":905},{"href":903,"rel":904},"https://wiki.archlinux.org/index.php/Install_Arch_Linux_on_a_USB_key#Installation_tweaks",[62],[906],{"type":25,"value":907},"8",{"type":20,"tag":116,"props":909,"children":911},{"code":910,"language":119,"meta":7,"className":120,"style":7},"[root@archlinux ~]# mkfs.ext4 -O \"^has_journal\" /dev/sdb2\n",[912],{"type":20,"tag":45,"props":913,"children":914},{"__ignoreMap":7},[915],{"type":20,"tag":126,"props":916,"children":917},{"class":128,"line":129},[918,922,926,931,936],{"type":20,"tag":126,"props":919,"children":920},{"style":434},[921],{"type":25,"value":695},{"type":20,"tag":126,"props":923,"children":924},{"style":440},[925],{"type":25,"value":443},{"type":20,"tag":126,"props":927,"children":928},{"style":434},[929],{"type":25,"value":930},"]# mkfs.ext4 -O ",{"type":20,"tag":126,"props":932,"children":933},{"style":138},[934],{"type":25,"value":935},"\"^has_journal\"",{"type":20,"tag":126,"props":937,"children":938},{"style":434},[939],{"type":25,"value":940}," /dev/sdb2\n",{"type":20,"tag":675,"props":942,"children":944},{"id":943},"mount-the-partitions-and-bootstrap-the-environment",[945],{"type":25,"value":946},"Mount the Partitions and Bootstrap the Environment",{"type":20,"tag":116,"props":948,"children":950},{"code":949,"language":119,"meta":7,"className":120,"style":7},"[root@archlinux ~]# mount /dev/sdb2 /mnt\n[root@archlinux ~]# mkdir -p /mnt/boot/efi\n[root@archlinux ~]# mount /dev/sdb1 /mnt/boot/efi\n",[951],{"type":20,"tag":45,"props":952,"children":953},{"__ignoreMap":7},[954,970,986],{"type":20,"tag":126,"props":955,"children":956},{"class":128,"line":129},[957,961,965],{"type":20,"tag":126,"props":958,"children":959},{"style":434},[960],{"type":25,"value":695},{"type":20,"tag":126,"props":962,"children":963},{"style":440},[964],{"type":25,"value":443},{"type":20,"tag":126,"props":966,"children":967},{"style":434},[968],{"type":25,"value":969},"]# mount /dev/sdb2 /mnt\n",{"type":20,"tag":126,"props":971,"children":972},{"class":128,"line":265},[973,977,981],{"type":20,"tag":126,"props":974,"children":975},{"style":434},[976],{"type":25,"value":695},{"type":20,"tag":126,"props":978,"children":979},{"style":440},[980],{"type":25,"value":443},{"type":20,"tag":126,"props":982,"children":983},{"style":434},[984],{"type":25,"value":985},"]# mkdir -p /mnt/boot/efi\n",{"type":20,"tag":126,"props":987,"children":988},{"class":128,"line":274},[989,993,997],{"type":20,"tag":126,"props":990,"children":991},{"style":434},[992],{"type":25,"value":695},{"type":20,"tag":126,"props":994,"children":995},{"style":440},[996],{"type":25,"value":443},{"type":20,"tag":126,"props":998,"children":999},{"style":434},[1000],{"type":25,"value":1001},"]# mount /dev/sdb1 /mnt/boot/efi\n",{"type":20,"tag":116,"props":1003,"children":1005},{"code":1004,"language":119,"meta":7,"className":120,"style":7},"[root@archlinux ~]# pacman -S arch-install-scripts\n[root@archlinux ~]# pacstrap /mnt base linux linux-firmware\n[root@archlinux ~]# genfstab -U /mnt >> /mnt/etc/fstab\n",[1006],{"type":20,"tag":45,"props":1007,"children":1008},{"__ignoreMap":7},[1009,1025,1041],{"type":20,"tag":126,"props":1010,"children":1011},{"class":128,"line":129},[1012,1016,1020],{"type":20,"tag":126,"props":1013,"children":1014},{"style":434},[1015],{"type":25,"value":695},{"type":20,"tag":126,"props":1017,"children":1018},{"style":440},[1019],{"type":25,"value":443},{"type":20,"tag":126,"props":1021,"children":1022},{"style":434},[1023],{"type":25,"value":1024},"]# pacman -S arch-install-scripts\n",{"type":20,"tag":126,"props":1026,"children":1027},{"class":128,"line":265},[1028,1032,1036],{"type":20,"tag":126,"props":1029,"children":1030},{"style":434},[1031],{"type":25,"value":695},{"type":20,"tag":126,"props":1033,"children":1034},{"style":440},[1035],{"type":25,"value":443},{"type":20,"tag":126,"props":1037,"children":1038},{"style":434},[1039],{"type":25,"value":1040},"]# pacstrap /mnt base linux linux-firmware\n",{"type":20,"tag":126,"props":1042,"children":1043},{"class":128,"line":274},[1044,1048,1052,1057,1062],{"type":20,"tag":126,"props":1045,"children":1046},{"style":434},[1047],{"type":25,"value":695},{"type":20,"tag":126,"props":1049,"children":1050},{"style":440},[1051],{"type":25,"value":443},{"type":20,"tag":126,"props":1053,"children":1054},{"style":434},[1055],{"type":25,"value":1056},"]# genfstab -U /mnt ",{"type":20,"tag":126,"props":1058,"children":1059},{"style":440},[1060],{"type":25,"value":1061},">>",{"type":20,"tag":126,"props":1063,"children":1064},{"style":434},[1065],{"type":25,"value":1066}," /mnt/etc/fstab\n",{"type":20,"tag":675,"props":1068,"children":1070},{"id":1069},"configure-the-new-environment",[1071],{"type":25,"value":1072},"Configure the New Environment",{"type":20,"tag":116,"props":1074,"children":1076},{"code":1075},"[root@archlinux ~]# arch-chroot /mnt\n",[1077],{"type":20,"tag":45,"props":1078,"children":1079},{"__ignoreMap":7},[1080],{"type":25,"value":1075},{"type":20,"tag":116,"props":1082,"children":1084},{"code":1083},"[root@archlinux /]# ln -sf /usr/share/zoneinfo/US/Eastern /etc/localtime\n[root@archlinux /]# hwclock --systohc\n[root@archlinux /]# sed -i 's/#en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen\n[root@archlinux /]# locale-gen\n[root@archlinux /]# echo \"LANG=en_US.UTF-8\" > /etc/locale.conf\n",[1085],{"type":20,"tag":45,"props":1086,"children":1087},{"__ignoreMap":7},[1088],{"type":25,"value":1083},{"type":20,"tag":116,"props":1090,"children":1092},{"code":1091},"[root@archlinux /]# hostnamectl set-hostname usb\n[root@archlinux /]# echo \"127.0.0.1 localhost\" >> /etc/hosts\n[root@archlinux /]# echo \"::1 localhost\" >> /etc/hosts\n",[1093],{"type":20,"tag":45,"props":1094,"children":1095},{"__ignoreMap":7},[1096],{"type":25,"value":1091},{"type":20,"tag":21,"props":1098,"children":1099},{},[1100,1102,1108,1110],{"type":25,"value":1101},"Note, one difference here from a standard installation is that the\n",{"type":20,"tag":45,"props":1103,"children":1105},{"className":1104},[],[1106],{"type":25,"value":1107},"--removable",{"type":25,"value":1109}," flag is specified when installing the GRUB bootloader.\n",{"type":20,"tag":54,"props":1111,"children":1112},{},[1113],{"type":20,"tag":58,"props":1114,"children":1117},{"href":1115,"rel":1116},"https://wiki.archlinux.org/index.php/GRUB#UEFI_systems",[62],[1118],{"type":25,"value":1119},"10",{"type":20,"tag":116,"props":1121,"children":1123},{"code":1122},"[root@archlinux /]# pacman -S grub\n[root@archlinux /]# grub-install --target=x86_64-efi --efi-directory=/boot/efi --removable --recheck\n[root@usb /]# grub-mkconfig -o /boot/grub/grub.cfg\n",[1124],{"type":20,"tag":45,"props":1125,"children":1126},{"__ignoreMap":7},[1127],{"type":25,"value":1122},{"type":20,"tag":21,"props":1129,"children":1130},{},[1131],{"type":25,"value":1132},"Shutdown the virtual machine, restart the host machine, and boot the newly\ncreated Arch Linux thumb-drive!",{"type":20,"tag":21,"props":1134,"children":1135},{},[1136],{"type":25,"value":1137},"🎉",{"type":20,"tag":92,"props":1139,"children":1141},{"id":1140},"side-note",[1142],{"type":25,"value":1143},"Side-note",{"type":20,"tag":21,"props":1145,"children":1146},{},[1147,1149,1155,1157,1162,1164],{"type":25,"value":1148},"It was attempted to use the ",{"type":20,"tag":45,"props":1150,"children":1152},{"className":1151},[],[1153],{"type":25,"value":1154},"controlvm usbattach",{"type":25,"value":1156}," command to pass the USB\ndevice to the guest machine, but this did not work as it expects the virtual\nmachine to already be running, and the ",{"type":20,"tag":45,"props":1158,"children":1160},{"className":1159},[],[1161],{"type":25,"value":236},{"type":25,"value":1163}," option runs prior to\nbooting the machine. ",{"type":20,"tag":54,"props":1165,"children":1166},{},[1167],{"type":20,"tag":58,"props":1168,"children":1171},{"href":1169,"rel":1170},"https://www.vagrantup.com/docs/virtualbox/configuration.html#vboxmanage-customizations",[62],[1172],{"type":25,"value":1173},"11",{"type":20,"tag":116,"props":1175,"children":1177},{"code":1176,"language":249,"meta":7,"className":250,"style":7},"Command: [\"controlvm\", \"060a716b-1965-49e2-bc56-12beed5df716\", \"usbattach36fc9e60-c465-11cf-8056-444553540000\"]\n\nStderr: VBoxManage.exe: error: Machine '060a716b-1965-49e2-bc56-12beed5df716' is not currently running.\n",[1178],{"type":20,"tag":45,"props":1179,"children":1180},{"__ignoreMap":7},[1181,1189,1196],{"type":20,"tag":126,"props":1182,"children":1183},{"class":128,"line":129},[1184],{"type":20,"tag":126,"props":1185,"children":1186},{},[1187],{"type":25,"value":1188},"Command: [\"controlvm\", \"060a716b-1965-49e2-bc56-12beed5df716\", \"usbattach36fc9e60-c465-11cf-8056-444553540000\"]\n",{"type":20,"tag":126,"props":1190,"children":1191},{"class":128,"line":265},[1192],{"type":20,"tag":126,"props":1193,"children":1194},{"emptyLinePlaceholder":278},[1195],{"type":25,"value":281},{"type":20,"tag":126,"props":1197,"children":1198},{"class":128,"line":274},[1199],{"type":20,"tag":126,"props":1200,"children":1201},{},[1202],{"type":25,"value":1203},"Stderr: VBoxManage.exe: error: Machine '060a716b-1965-49e2-bc56-12beed5df716' is not currently running.\n",{"type":20,"tag":92,"props":1205,"children":1207},{"id":1206},"references",[1208],{"type":25,"value":1209},"References",{"type":20,"tag":1211,"props":1212,"children":1213},"ol",{},[1214,1224,1233,1242,1251,1260,1269,1278,1287,1296,1305],{"type":20,"tag":1215,"props":1216,"children":1217},"li",{},[1218],{"type":20,"tag":58,"props":1219,"children":1221},{"href":60,"rel":1220},[62],[1222],{"type":25,"value":1223},"Docker Desktop on Mac vs. Docker Toolbox",{"type":20,"tag":1215,"props":1225,"children":1226},{},[1227],{"type":20,"tag":58,"props":1228,"children":1230},{"href":70,"rel":1229},[62],[1231],{"type":25,"value":1232},"GitHub - HyperKit",{"type":20,"tag":1215,"props":1234,"children":1235},{},[1236],{"type":20,"tag":58,"props":1237,"children":1239},{"href":78,"rel":1238},[62],[1240],{"type":25,"value":1241},"GitHub - Docker for Mac - Issue #900",{"type":20,"tag":1215,"props":1243,"children":1244},{},[1245],{"type":20,"tag":58,"props":1246,"children":1248},{"href":108,"rel":1247},[62],[1249],{"type":25,"value":1250},"Vagrant Cloud - Arch Linux",{"type":20,"tag":1215,"props":1252,"children":1253},{},[1254],{"type":20,"tag":58,"props":1255,"children":1257},{"href":216,"rel":1256},[62],[1258],{"type":25,"value":1259},"Attaching USB Devices to VirtualBox Guests using VBoxManage",{"type":20,"tag":1215,"props":1261,"children":1262},{},[1263],{"type":20,"tag":58,"props":1264,"children":1266},{"href":224,"rel":1265},[62],[1267],{"type":25,"value":1268},"GitHub Gist - Vagrant USB Filter",{"type":20,"tag":1215,"props":1270,"children":1271},{},[1272],{"type":20,"tag":58,"props":1273,"children":1275},{"href":841,"rel":1274},[62],[1276],{"type":25,"value":1277},"Arch Linux Wiki - EFI System Partition - Format Partitions",{"type":20,"tag":1215,"props":1279,"children":1280},{},[1281],{"type":20,"tag":58,"props":1282,"children":1284},{"href":903,"rel":1283},[62],[1285],{"type":25,"value":1286},"Arch Linux Wiki - Arch Linux on USB - Installation Tweaks",{"type":20,"tag":1215,"props":1288,"children":1289},{},[1290],{"type":20,"tag":58,"props":1291,"children":1293},{"href":667,"rel":1292},[62],[1294],{"type":25,"value":1295},"Arch Linux Wiki - Installation Guide",{"type":20,"tag":1215,"props":1297,"children":1298},{},[1299],{"type":20,"tag":58,"props":1300,"children":1302},{"href":1115,"rel":1301},[62],[1303],{"type":25,"value":1304},"Arch Linux Wiki - GRUB - UEFI Systems",{"type":20,"tag":1215,"props":1306,"children":1307},{},[1308],{"type":20,"tag":58,"props":1309,"children":1311},{"href":1169,"rel":1310},[62],[1312],{"type":25,"value":1313},"Vagrant VBoxManage Customizations ",{"type":20,"tag":1315,"props":1316,"children":1317},"style",{},[1318],{"type":25,"value":1319},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":265,"depth":265,"links":1321},[1322,1323,1329,1330],{"id":94,"depth":265,"text":97},{"id":656,"depth":265,"text":659,"children":1324},[1325,1326,1327,1328],{"id":677,"depth":274,"text":680},{"id":827,"depth":274,"text":830},{"id":943,"depth":274,"text":946},{"id":1069,"depth":274,"text":1072},{"id":1140,"depth":265,"text":1143},{"id":1206,"depth":265,"text":1209},"markdown","content:articles:persistent-archlinux-usb.md","content","articles/persistent-archlinux-usb.md","md",1727638398055] \ No newline at end of file diff --git a/articles/persistent-archlinux-usb/index.html b/articles/persistent-archlinux-usb/index.html index 26f6f1ab..0e0b09f9 100644 --- a/articles/persistent-archlinux-usb/index.html +++ b/articles/persistent-archlinux-usb/index.html @@ -4,37 +4,36 @@ - - + + - - - - + + + + - - + - - - - - - - - - - - - - - - - - -

            Create a Persistent Arch Linux Bootable USB with Vagrant

            When installing a linux distribution, it is common for the instructions to have + + + + + + + + + + + + + + + + + +

            Create a Persistent Arch Linux Bootable USB with Vagrant

            When installing a linux distribution, it is common for the instructions to have the user create a bootable USB, boot from the device, and proceed with the installation procedure from that live medium. However, this blog post will outline an alternative approach where a virtual machine created with Vagrant @@ -124,5 +123,5 @@ booting the machine. 11

            Command: ["controlvm", "060a716b-1965-49e2-bc56-12beed5df716", "usbattach36fc9e60-c465-11cf-8056-444553540000"]
             
             Stderr: VBoxManage.exe: error: Machine '060a716b-1965-49e2-bc56-12beed5df716' is not currently running.
            -

            References

            1. Docker Desktop on Mac vs. Docker Toolbox
            2. GitHub - HyperKit
            3. GitHub - Docker for Mac - Issue #900
            4. Vagrant Cloud - Arch Linux
            5. Attaching USB Devices to VirtualBox Guests using VBoxManage
            6. GitHub Gist - Vagrant USB Filter
            7. Arch Linux Wiki - EFI System Partition - Format Partitions
            8. Arch Linux Wiki - Arch Linux on USB - Installation Tweaks
            9. Arch Linux Wiki - Installation Guide
            10. Arch Linux Wiki - GRUB - UEFI Systems
            11. Vagrant VBoxManage Customizations
            - \ No newline at end of file +

            References

            1. Docker Desktop on Mac vs. Docker Toolbox
            2. GitHub - HyperKit
            3. GitHub - Docker for Mac - Issue #900
            4. Vagrant Cloud - Arch Linux
            5. Attaching USB Devices to VirtualBox Guests using VBoxManage
            6. GitHub Gist - Vagrant USB Filter
            7. Arch Linux Wiki - EFI System Partition - Format Partitions
            8. Arch Linux Wiki - Arch Linux on USB - Installation Tweaks
            9. Arch Linux Wiki - Installation Guide
            10. Arch Linux Wiki - GRUB - UEFI Systems
            11. Vagrant VBoxManage Customizations
            + \ No newline at end of file diff --git a/articles/podcast-transcription-whispercpp/_payload.json b/articles/podcast-transcription-whispercpp/_payload.json index c3d8cff4..44476b43 100644 --- a/articles/podcast-transcription-whispercpp/_payload.json +++ b/articles/podcast-transcription-whispercpp/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":750},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"draft":6,"date":10,"tags":11,"categories":14,"excerpt":16,"body":55,"_type":744,"_id":745,"_source":746,"_file":747,"_stem":748,"_extension":749},"/articles/podcast-transcription-whispercpp","articles",false,"","Easily Transcribe Podcasts with Whisper.cpp","If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive whisper.cpp project. This high-performance fork of OpenAI's Whisper can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the Alter Everything podcast.","2024-01-08",[12,13],"whisper.cpp","ml",[15],"programming",{"type":17,"children":18},"root",[19],{"type":20,"tag":21,"props":22,"children":23},"element","p",{},[24,27,35,37,44,46,53],{"type":25,"value":26},"text","If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive ",{"type":20,"tag":28,"props":29,"children":33},"a",{"href":30,"rel":31},"https://github.com/ggerganov/whisper.cpp",[32],"nofollow",[34],{"type":25,"value":12},{"type":25,"value":36}," project. This high-performance fork of ",{"type":20,"tag":28,"props":38,"children":41},{"href":39,"rel":40},"https://github.com/openai/whisper",[32],[42],{"type":25,"value":43},"OpenAI's Whisper",{"type":25,"value":45}," can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the ",{"type":20,"tag":28,"props":47,"children":50},{"href":48,"rel":49},"https://podcasts.apple.com/us/podcast/alter-everything/id1356137854",[32],[51],{"type":25,"value":52},"Alter Everything",{"type":25,"value":54}," podcast.",{"type":17,"children":56,"toc":739},[57,79,86,130,222,234,399,412,424,550,555,720,725,733],{"type":20,"tag":21,"props":58,"children":59},{},[60,61,66,67,72,73,78],{"type":25,"value":26},{"type":20,"tag":28,"props":62,"children":64},{"href":30,"rel":63},[32],[65],{"type":25,"value":12},{"type":25,"value":36},{"type":20,"tag":28,"props":68,"children":70},{"href":39,"rel":69},[32],[71],{"type":25,"value":43},{"type":25,"value":45},{"type":20,"tag":28,"props":74,"children":76},{"href":48,"rel":75},[32],[77],{"type":25,"value":52},{"type":25,"value":54},{"type":20,"tag":80,"props":81,"children":83},"h2",{"id":82},"obtain-audio-files",[84],{"type":25,"value":85},"Obtain Audio File(s)",{"type":20,"tag":21,"props":87,"children":88},{},[89,91,98,100,106,108,113,115,120,122,128],{"type":25,"value":90},"First, let's get the ",{"type":20,"tag":92,"props":93,"children":95},"code",{"className":94},[],[96],{"type":25,"value":97},"wav",{"type":25,"value":99}," file from YouTube using the ",{"type":20,"tag":92,"props":101,"children":103},{"className":102},[],[104],{"type":25,"value":105},"youtube-dl",{"type":25,"value":107}," utility. It should be noted that ",{"type":20,"tag":92,"props":109,"children":111},{"className":110},[],[112],{"type":25,"value":12},{"type":25,"value":114}," expects ",{"type":20,"tag":92,"props":116,"children":118},{"className":117},[],[119],{"type":25,"value":97},{"type":25,"value":121}," filetypes, and this utility defaults to ",{"type":20,"tag":92,"props":123,"children":125},{"className":124},[],[126],{"type":25,"value":127},"mp3",{"type":25,"value":129},".",{"type":20,"tag":131,"props":132,"children":136},"pre",{"code":133,"language":134,"meta":7,"className":135,"style":7}," $ youtube-dl \\\n --extract-audio \\\n --audio-format wav \\\n --output podcast.wav \\\n \"https://www.youtube.com/watch?v=CoUN690wSYQ\"\n","sh","language-sh shiki shiki-themes github-light",[137],{"type":20,"tag":92,"props":138,"children":139},{"__ignoreMap":7},[140,164,177,195,213],{"type":20,"tag":141,"props":142,"children":145},"span",{"class":143,"line":144},"line",1,[146,152,158],{"type":20,"tag":141,"props":147,"children":149},{"style":148},"--shiki-default:#6F42C1",[150],{"type":25,"value":151}," $",{"type":20,"tag":141,"props":153,"children":155},{"style":154},"--shiki-default:#032F62",[156],{"type":25,"value":157}," youtube-dl",{"type":20,"tag":141,"props":159,"children":161},{"style":160},"--shiki-default:#005CC5",[162],{"type":25,"value":163}," \\\n",{"type":20,"tag":141,"props":165,"children":167},{"class":143,"line":166},2,[168,173],{"type":20,"tag":141,"props":169,"children":170},{"style":160},[171],{"type":25,"value":172}," --extract-audio",{"type":20,"tag":141,"props":174,"children":175},{"style":160},[176],{"type":25,"value":163},{"type":20,"tag":141,"props":178,"children":180},{"class":143,"line":179},3,[181,186,191],{"type":20,"tag":141,"props":182,"children":183},{"style":160},[184],{"type":25,"value":185}," --audio-format",{"type":20,"tag":141,"props":187,"children":188},{"style":154},[189],{"type":25,"value":190}," wav",{"type":20,"tag":141,"props":192,"children":193},{"style":160},[194],{"type":25,"value":163},{"type":20,"tag":141,"props":196,"children":198},{"class":143,"line":197},4,[199,204,209],{"type":20,"tag":141,"props":200,"children":201},{"style":160},[202],{"type":25,"value":203}," --output",{"type":20,"tag":141,"props":205,"children":206},{"style":154},[207],{"type":25,"value":208}," podcast.wav",{"type":20,"tag":141,"props":210,"children":211},{"style":160},[212],{"type":25,"value":163},{"type":20,"tag":141,"props":214,"children":216},{"class":143,"line":215},5,[217],{"type":20,"tag":141,"props":218,"children":219},{"style":154},[220],{"type":25,"value":221}," \"https://www.youtube.com/watch?v=CoUN690wSYQ\"\n",{"type":20,"tag":21,"props":223,"children":224},{},[225,227,232],{"type":25,"value":226},"This file has a 44.1 kHz sample rate, and ",{"type":20,"tag":92,"props":228,"children":230},{"className":229},[],[231],{"type":25,"value":12},{"type":25,"value":233}," expects 16 kHz, so let's go ahead and convert that.",{"type":20,"tag":131,"props":235,"children":237},{"code":236,"language":134,"meta":7,"className":135,"style":7}," $ file podcast.wav\npodcast.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz\n\n $ ffmpeg -i podcast.wav -ar 16000 podcast-16khz.wav\n\n $ file podcast-16khz.wav\npodcast-16khz.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 16000 Hz\n\n# NOTE: it looks like it's possible to specify this conversion as a post-process as a\n# flag to the `youtube-dl` command -- I will explore this further next time...\n# youtube-dl --extract-audio --audio-quality 0 --audio-format mp3 --postprocessor-args \"-ar 44100\" %dl%\n",[238],{"type":20,"tag":92,"props":239,"children":240},{"__ignoreMap":7},[241,258,277,286,322,329,345,363,371,381,390],{"type":20,"tag":141,"props":242,"children":243},{"class":143,"line":144},[244,248,253],{"type":20,"tag":141,"props":245,"children":246},{"style":148},[247],{"type":25,"value":151},{"type":20,"tag":141,"props":249,"children":250},{"style":154},[251],{"type":25,"value":252}," file",{"type":20,"tag":141,"props":254,"children":255},{"style":154},[256],{"type":25,"value":257}," podcast.wav\n",{"type":20,"tag":141,"props":259,"children":260},{"class":143,"line":166},[261,266,271],{"type":20,"tag":141,"props":262,"children":263},{"style":148},[264],{"type":25,"value":265},"podcast.wav:",{"type":20,"tag":141,"props":267,"children":268},{"style":154},[269],{"type":25,"value":270}," RIFF",{"type":20,"tag":141,"props":272,"children":274},{"style":273},"--shiki-default:#24292E",[275],{"type":25,"value":276}," (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz\n",{"type":20,"tag":141,"props":278,"children":279},{"class":143,"line":179},[280],{"type":20,"tag":141,"props":281,"children":283},{"emptyLinePlaceholder":282},true,[284],{"type":25,"value":285},"\n",{"type":20,"tag":141,"props":287,"children":288},{"class":143,"line":197},[289,293,298,303,307,312,317],{"type":20,"tag":141,"props":290,"children":291},{"style":148},[292],{"type":25,"value":151},{"type":20,"tag":141,"props":294,"children":295},{"style":154},[296],{"type":25,"value":297}," ffmpeg",{"type":20,"tag":141,"props":299,"children":300},{"style":160},[301],{"type":25,"value":302}," -i",{"type":20,"tag":141,"props":304,"children":305},{"style":154},[306],{"type":25,"value":208},{"type":20,"tag":141,"props":308,"children":309},{"style":160},[310],{"type":25,"value":311}," -ar",{"type":20,"tag":141,"props":313,"children":314},{"style":160},[315],{"type":25,"value":316}," 16000",{"type":20,"tag":141,"props":318,"children":319},{"style":154},[320],{"type":25,"value":321}," podcast-16khz.wav\n",{"type":20,"tag":141,"props":323,"children":324},{"class":143,"line":215},[325],{"type":20,"tag":141,"props":326,"children":327},{"emptyLinePlaceholder":282},[328],{"type":25,"value":285},{"type":20,"tag":141,"props":330,"children":332},{"class":143,"line":331},6,[333,337,341],{"type":20,"tag":141,"props":334,"children":335},{"style":148},[336],{"type":25,"value":151},{"type":20,"tag":141,"props":338,"children":339},{"style":154},[340],{"type":25,"value":252},{"type":20,"tag":141,"props":342,"children":343},{"style":154},[344],{"type":25,"value":321},{"type":20,"tag":141,"props":346,"children":348},{"class":143,"line":347},7,[349,354,358],{"type":20,"tag":141,"props":350,"children":351},{"style":148},[352],{"type":25,"value":353},"podcast-16khz.wav:",{"type":20,"tag":141,"props":355,"children":356},{"style":154},[357],{"type":25,"value":270},{"type":20,"tag":141,"props":359,"children":360},{"style":273},[361],{"type":25,"value":362}," (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 16000 Hz\n",{"type":20,"tag":141,"props":364,"children":366},{"class":143,"line":365},8,[367],{"type":20,"tag":141,"props":368,"children":369},{"emptyLinePlaceholder":282},[370],{"type":25,"value":285},{"type":20,"tag":141,"props":372,"children":374},{"class":143,"line":373},9,[375],{"type":20,"tag":141,"props":376,"children":378},{"style":377},"--shiki-default:#6A737D",[379],{"type":25,"value":380},"# NOTE: it looks like it's possible to specify this conversion as a post-process as a\n",{"type":20,"tag":141,"props":382,"children":384},{"class":143,"line":383},10,[385],{"type":20,"tag":141,"props":386,"children":387},{"style":377},[388],{"type":25,"value":389},"# flag to the `youtube-dl` command -- I will explore this further next time...\n",{"type":20,"tag":141,"props":391,"children":393},{"class":143,"line":392},11,[394],{"type":20,"tag":141,"props":395,"children":396},{"style":377},[397],{"type":25,"value":398},"# youtube-dl --extract-audio --audio-quality 0 --audio-format mp3 --postprocessor-args \"-ar 44100\" %dl%\n",{"type":20,"tag":80,"props":400,"children":402},{"id":401},"build-whispercpp-transcribe-audio",[403,405,410],{"type":25,"value":404},"Build ",{"type":20,"tag":92,"props":406,"children":408},{"className":407},[],[409],{"type":25,"value":12},{"type":25,"value":411}," & Transcribe Audio",{"type":20,"tag":21,"props":413,"children":414},{},[415,417,422],{"type":25,"value":416},"Then, let's get the latest version of ",{"type":20,"tag":92,"props":418,"children":420},{"className":419},[],[421],{"type":25,"value":12},{"type":25,"value":423},", download the English Whisper model, and build the example.",{"type":20,"tag":131,"props":425,"children":427},{"code":426,"language":134,"meta":7,"className":135,"style":7},"# Clone the `whisper.cpp` repository\n $ git clone --depth 1 git@github.com:ggerganov/whisper.cpp && cd whisper.cpp\n\n# Download the English Whisper model in `ggml` format\n $ bash ./models/download-ggml-model.sh base.en\n\n# Build the main example\n $ make\n",[428],{"type":20,"tag":92,"props":429,"children":430},{"__ignoreMap":7},[431,439,486,493,501,523,530,538],{"type":20,"tag":141,"props":432,"children":433},{"class":143,"line":144},[434],{"type":20,"tag":141,"props":435,"children":436},{"style":377},[437],{"type":25,"value":438},"# Clone the `whisper.cpp` repository\n",{"type":20,"tag":141,"props":440,"children":441},{"class":143,"line":166},[442,446,451,456,461,466,471,476,481],{"type":20,"tag":141,"props":443,"children":444},{"style":148},[445],{"type":25,"value":151},{"type":20,"tag":141,"props":447,"children":448},{"style":154},[449],{"type":25,"value":450}," git",{"type":20,"tag":141,"props":452,"children":453},{"style":154},[454],{"type":25,"value":455}," clone",{"type":20,"tag":141,"props":457,"children":458},{"style":160},[459],{"type":25,"value":460}," --depth",{"type":20,"tag":141,"props":462,"children":463},{"style":160},[464],{"type":25,"value":465}," 1",{"type":20,"tag":141,"props":467,"children":468},{"style":154},[469],{"type":25,"value":470}," git@github.com:ggerganov/whisper.cpp",{"type":20,"tag":141,"props":472,"children":473},{"style":273},[474],{"type":25,"value":475}," && ",{"type":20,"tag":141,"props":477,"children":478},{"style":160},[479],{"type":25,"value":480},"cd",{"type":20,"tag":141,"props":482,"children":483},{"style":154},[484],{"type":25,"value":485}," whisper.cpp\n",{"type":20,"tag":141,"props":487,"children":488},{"class":143,"line":179},[489],{"type":20,"tag":141,"props":490,"children":491},{"emptyLinePlaceholder":282},[492],{"type":25,"value":285},{"type":20,"tag":141,"props":494,"children":495},{"class":143,"line":197},[496],{"type":20,"tag":141,"props":497,"children":498},{"style":377},[499],{"type":25,"value":500},"# Download the English Whisper model in `ggml` format\n",{"type":20,"tag":141,"props":502,"children":503},{"class":143,"line":215},[504,508,513,518],{"type":20,"tag":141,"props":505,"children":506},{"style":148},[507],{"type":25,"value":151},{"type":20,"tag":141,"props":509,"children":510},{"style":154},[511],{"type":25,"value":512}," bash",{"type":20,"tag":141,"props":514,"children":515},{"style":154},[516],{"type":25,"value":517}," ./models/download-ggml-model.sh",{"type":20,"tag":141,"props":519,"children":520},{"style":154},[521],{"type":25,"value":522}," base.en\n",{"type":20,"tag":141,"props":524,"children":525},{"class":143,"line":331},[526],{"type":20,"tag":141,"props":527,"children":528},{"emptyLinePlaceholder":282},[529],{"type":25,"value":285},{"type":20,"tag":141,"props":531,"children":532},{"class":143,"line":347},[533],{"type":20,"tag":141,"props":534,"children":535},{"style":377},[536],{"type":25,"value":537},"# Build the main example\n",{"type":20,"tag":141,"props":539,"children":540},{"class":143,"line":365},[541,545],{"type":20,"tag":141,"props":542,"children":543},{"style":148},[544],{"type":25,"value":151},{"type":20,"tag":141,"props":546,"children":547},{"style":154},[548],{"type":25,"value":549}," make\n",{"type":20,"tag":21,"props":551,"children":552},{},[553],{"type":25,"value":554},"And finally, let's transcribe that podcast!",{"type":20,"tag":131,"props":556,"children":558},{"code":557,"language":134,"meta":7,"className":135,"style":7}," $ ./main \\\n -m ~/workspace/whisper.cpp/models/ggml-base.en.bin \\\n -f ~/Downloads/podcast-16khz.wav \\\n --output-vtt \\\n --output-file out\n\n# whisper_print_timings: load time = 114.71 ms\n# whisper_print_timings: fallbacks = 0 p / 0 h\n# whisper_print_timings: mel time = 692.20 ms\n# whisper_print_timings: sample time = 22278.10 ms / 27893 runs ( 0.80 ms per run)\n# whisper_print_timings: encode time = 10000.75 ms / 55 runs ( 181.83 ms per run)\n# whisper_print_timings: decode time = 331.77 ms / 54 runs ( 6.14 ms per run)\n# whisper_print_timings: batchd time = 45236.73 ms / 27566 runs ( 1.64 ms per run)\n# whisper_print_timings: prompt time = 1921.90 ms / 11832 runs ( 0.16 ms per run)\n# whisper_print_timings: total time = 80709.54 ms\n",[559],{"type":20,"tag":92,"props":560,"children":561},{"__ignoreMap":7},[562,578,595,612,624,637,644,652,660,668,676,684,693,702,711],{"type":20,"tag":141,"props":563,"children":564},{"class":143,"line":144},[565,569,574],{"type":20,"tag":141,"props":566,"children":567},{"style":148},[568],{"type":25,"value":151},{"type":20,"tag":141,"props":570,"children":571},{"style":154},[572],{"type":25,"value":573}," ./main",{"type":20,"tag":141,"props":575,"children":576},{"style":160},[577],{"type":25,"value":163},{"type":20,"tag":141,"props":579,"children":580},{"class":143,"line":166},[581,586,591],{"type":20,"tag":141,"props":582,"children":583},{"style":160},[584],{"type":25,"value":585}," -m",{"type":20,"tag":141,"props":587,"children":588},{"style":154},[589],{"type":25,"value":590}," ~/workspace/whisper.cpp/models/ggml-base.en.bin",{"type":20,"tag":141,"props":592,"children":593},{"style":160},[594],{"type":25,"value":163},{"type":20,"tag":141,"props":596,"children":597},{"class":143,"line":179},[598,603,608],{"type":20,"tag":141,"props":599,"children":600},{"style":160},[601],{"type":25,"value":602}," -f",{"type":20,"tag":141,"props":604,"children":605},{"style":154},[606],{"type":25,"value":607}," ~/Downloads/podcast-16khz.wav",{"type":20,"tag":141,"props":609,"children":610},{"style":160},[611],{"type":25,"value":163},{"type":20,"tag":141,"props":613,"children":614},{"class":143,"line":197},[615,620],{"type":20,"tag":141,"props":616,"children":617},{"style":160},[618],{"type":25,"value":619}," --output-vtt",{"type":20,"tag":141,"props":621,"children":622},{"style":160},[623],{"type":25,"value":163},{"type":20,"tag":141,"props":625,"children":626},{"class":143,"line":215},[627,632],{"type":20,"tag":141,"props":628,"children":629},{"style":160},[630],{"type":25,"value":631}," --output-file",{"type":20,"tag":141,"props":633,"children":634},{"style":154},[635],{"type":25,"value":636}," out\n",{"type":20,"tag":141,"props":638,"children":639},{"class":143,"line":331},[640],{"type":20,"tag":141,"props":641,"children":642},{"emptyLinePlaceholder":282},[643],{"type":25,"value":285},{"type":20,"tag":141,"props":645,"children":646},{"class":143,"line":347},[647],{"type":20,"tag":141,"props":648,"children":649},{"style":377},[650],{"type":25,"value":651},"# whisper_print_timings: load time = 114.71 ms\n",{"type":20,"tag":141,"props":653,"children":654},{"class":143,"line":365},[655],{"type":20,"tag":141,"props":656,"children":657},{"style":377},[658],{"type":25,"value":659},"# whisper_print_timings: fallbacks = 0 p / 0 h\n",{"type":20,"tag":141,"props":661,"children":662},{"class":143,"line":373},[663],{"type":20,"tag":141,"props":664,"children":665},{"style":377},[666],{"type":25,"value":667},"# whisper_print_timings: mel time = 692.20 ms\n",{"type":20,"tag":141,"props":669,"children":670},{"class":143,"line":383},[671],{"type":20,"tag":141,"props":672,"children":673},{"style":377},[674],{"type":25,"value":675},"# whisper_print_timings: sample time = 22278.10 ms / 27893 runs ( 0.80 ms per run)\n",{"type":20,"tag":141,"props":677,"children":678},{"class":143,"line":392},[679],{"type":20,"tag":141,"props":680,"children":681},{"style":377},[682],{"type":25,"value":683},"# whisper_print_timings: encode time = 10000.75 ms / 55 runs ( 181.83 ms per run)\n",{"type":20,"tag":141,"props":685,"children":687},{"class":143,"line":686},12,[688],{"type":20,"tag":141,"props":689,"children":690},{"style":377},[691],{"type":25,"value":692},"# whisper_print_timings: decode time = 331.77 ms / 54 runs ( 6.14 ms per run)\n",{"type":20,"tag":141,"props":694,"children":696},{"class":143,"line":695},13,[697],{"type":20,"tag":141,"props":698,"children":699},{"style":377},[700],{"type":25,"value":701},"# whisper_print_timings: batchd time = 45236.73 ms / 27566 runs ( 1.64 ms per run)\n",{"type":20,"tag":141,"props":703,"children":705},{"class":143,"line":704},14,[706],{"type":20,"tag":141,"props":707,"children":708},{"style":377},[709],{"type":25,"value":710},"# whisper_print_timings: prompt time = 1921.90 ms / 11832 runs ( 0.16 ms per run)\n",{"type":20,"tag":141,"props":712,"children":714},{"class":143,"line":713},15,[715],{"type":20,"tag":141,"props":716,"children":717},{"style":377},[718],{"type":25,"value":719},"# whisper_print_timings: total time = 80709.54 ms\n",{"type":20,"tag":21,"props":721,"children":722},{},[723],{"type":25,"value":724},"A full podcast transcribed in ~80 seconds on an M1 Mac Mini -- not too bad!",{"type":20,"tag":131,"props":726,"children":728},{"code":727},"# out.vtt\n\n00:00:00.000 --> 00:00:06.480\n >> Hi everyone. We recently launched a short engagement feedback survey for the Alter Everything\n\n00:00:06.480 --> 00:00:11.360\n podcast. Click the link in the episode description wherever you're listening to let us know what\n\n00:00:11.360 --> 00:00:16.320\n you think and help us improve our show.\n\n00:00:16.320 --> 00:00:21.200\n Welcome to Alter Everything, a podcast about data science and analytics culture. I'm Megan\n\n00:00:21.200 --> 00:00:26.440\n Dibble and today I'm talking with Nick Schrock, CTO and founder of Dagster Labs. We discussed\n\n00:00:26.440 --> 00:00:31.560\n data engineering trends, challenges in the field, why he started his company, and what\n\n00:00:31.560 --> 00:00:38.960\n makes him excited about the future of data engineering. Let's get started.\n\n00:00:38.960 --> 00:00:42.720\n >> Hi, Nick. It's great to have you on our show today. Thanks for being here.\n\n00:00:42.720 --> 00:00:43.920\n >> Thanks for having me.\n\n00:00:43.920 --> 00:00:48.280\n >> Yeah. Could you start off by giving an introduction to yourself for our listeners?\n\n00:00:48.280 --> 00:00:52.920\n >> Sure. My name is Nick Schrock. I'm the CTO and founder of Dagster Labs. There's the\n\n00:00:52.920 --> 00:00:59.520\n company behind Dagster, which is a data orchestration framework. Prior to doing this, I was an engineer\n\n00:00:59.520 --> 00:01:05.960\n at Facebook from 2009, 2017. While I was there, I found a team called product infrastructure\n\n00:01:05.960 --> 00:01:09.800\n whose goal was to make our application developers more efficient and productive, and a bunch\n\n00:01:09.800 --> 00:01:13.840\n of open source work came out of that actually, one of which was React, which I had nothing\n\n00:01:13.840 --> 00:01:18.040\n to do with, but actually the CEO of Dagster Labs co-created and I personally co-created\n\n00:01:18.040 --> 00:01:22.640\n GraphQL. So as I like to say, Pete and I were present at the creation of the full hipster\n\n00:01:22.640 --> 00:01:28.680\n stack. I moved on to Facebook in 2017, figuring out what to do next, and this data engineering\n\n00:01:28.680 --> 00:01:32.960\n and data orchestration problem really got me hooked actually quite soon after I left,\n\n00:01:32.960 --> 00:01:36.280\n and the rest is history. I'm sure we'll get into that more.\n",[729],{"type":20,"tag":92,"props":730,"children":731},{"__ignoreMap":7},[732],{"type":25,"value":727},{"type":20,"tag":734,"props":735,"children":736},"style",{},[737],{"type":25,"value":738},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":166,"depth":166,"links":740},[741,742],{"id":82,"depth":166,"text":85},{"id":401,"depth":166,"text":743},"Build whisper.cpp & Transcribe Audio","markdown","content:articles:podcast-transcription-whispercpp.md","content","articles/podcast-transcription-whispercpp.md","articles/podcast-transcription-whispercpp","md",1726174739472] \ No newline at end of file +[{"data":1,"prerenderedAt":749},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"draft":6,"date":10,"tags":11,"categories":14,"excerpt":16,"body":55,"_type":744,"_id":745,"_source":746,"_file":747,"_extension":748},"/articles/podcast-transcription-whispercpp","articles",false,"","Easily Transcribe Podcasts with Whisper.cpp","If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive whisper.cpp project. This high-performance fork of OpenAI's Whisper can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the Alter Everything podcast.","2024-01-08",[12,13],"whisper.cpp","ml",[15],"programming",{"type":17,"children":18},"root",[19],{"type":20,"tag":21,"props":22,"children":23},"element","p",{},[24,27,35,37,44,46,53],{"type":25,"value":26},"text","If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive ",{"type":20,"tag":28,"props":29,"children":33},"a",{"href":30,"rel":31},"https://github.com/ggerganov/whisper.cpp",[32],"nofollow",[34],{"type":25,"value":12},{"type":25,"value":36}," project. This high-performance fork of ",{"type":20,"tag":28,"props":38,"children":41},{"href":39,"rel":40},"https://github.com/openai/whisper",[32],[42],{"type":25,"value":43},"OpenAI's Whisper",{"type":25,"value":45}," can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the ",{"type":20,"tag":28,"props":47,"children":50},{"href":48,"rel":49},"https://podcasts.apple.com/us/podcast/alter-everything/id1356137854",[32],[51],{"type":25,"value":52},"Alter Everything",{"type":25,"value":54}," podcast.",{"type":17,"children":56,"toc":739},[57,79,86,130,222,234,399,412,424,550,555,720,725,733],{"type":20,"tag":21,"props":58,"children":59},{},[60,61,66,67,72,73,78],{"type":25,"value":26},{"type":20,"tag":28,"props":62,"children":64},{"href":30,"rel":63},[32],[65],{"type":25,"value":12},{"type":25,"value":36},{"type":20,"tag":28,"props":68,"children":70},{"href":39,"rel":69},[32],[71],{"type":25,"value":43},{"type":25,"value":45},{"type":20,"tag":28,"props":74,"children":76},{"href":48,"rel":75},[32],[77],{"type":25,"value":52},{"type":25,"value":54},{"type":20,"tag":80,"props":81,"children":83},"h2",{"id":82},"obtain-audio-files",[84],{"type":25,"value":85},"Obtain Audio File(s)",{"type":20,"tag":21,"props":87,"children":88},{},[89,91,98,100,106,108,113,115,120,122,128],{"type":25,"value":90},"First, let's get the ",{"type":20,"tag":92,"props":93,"children":95},"code",{"className":94},[],[96],{"type":25,"value":97},"wav",{"type":25,"value":99}," file from YouTube using the ",{"type":20,"tag":92,"props":101,"children":103},{"className":102},[],[104],{"type":25,"value":105},"youtube-dl",{"type":25,"value":107}," utility. It should be noted that ",{"type":20,"tag":92,"props":109,"children":111},{"className":110},[],[112],{"type":25,"value":12},{"type":25,"value":114}," expects ",{"type":20,"tag":92,"props":116,"children":118},{"className":117},[],[119],{"type":25,"value":97},{"type":25,"value":121}," filetypes, and this utility defaults to ",{"type":20,"tag":92,"props":123,"children":125},{"className":124},[],[126],{"type":25,"value":127},"mp3",{"type":25,"value":129},".",{"type":20,"tag":131,"props":132,"children":136},"pre",{"code":133,"language":134,"meta":7,"className":135,"style":7}," $ youtube-dl \\\n --extract-audio \\\n --audio-format wav \\\n --output podcast.wav \\\n \"https://www.youtube.com/watch?v=CoUN690wSYQ\"\n","sh","language-sh shiki shiki-themes github-light",[137],{"type":20,"tag":92,"props":138,"children":139},{"__ignoreMap":7},[140,164,177,195,213],{"type":20,"tag":141,"props":142,"children":145},"span",{"class":143,"line":144},"line",1,[146,152,158],{"type":20,"tag":141,"props":147,"children":149},{"style":148},"--shiki-default:#6F42C1",[150],{"type":25,"value":151}," $",{"type":20,"tag":141,"props":153,"children":155},{"style":154},"--shiki-default:#032F62",[156],{"type":25,"value":157}," youtube-dl",{"type":20,"tag":141,"props":159,"children":161},{"style":160},"--shiki-default:#005CC5",[162],{"type":25,"value":163}," \\\n",{"type":20,"tag":141,"props":165,"children":167},{"class":143,"line":166},2,[168,173],{"type":20,"tag":141,"props":169,"children":170},{"style":160},[171],{"type":25,"value":172}," --extract-audio",{"type":20,"tag":141,"props":174,"children":175},{"style":160},[176],{"type":25,"value":163},{"type":20,"tag":141,"props":178,"children":180},{"class":143,"line":179},3,[181,186,191],{"type":20,"tag":141,"props":182,"children":183},{"style":160},[184],{"type":25,"value":185}," --audio-format",{"type":20,"tag":141,"props":187,"children":188},{"style":154},[189],{"type":25,"value":190}," wav",{"type":20,"tag":141,"props":192,"children":193},{"style":160},[194],{"type":25,"value":163},{"type":20,"tag":141,"props":196,"children":198},{"class":143,"line":197},4,[199,204,209],{"type":20,"tag":141,"props":200,"children":201},{"style":160},[202],{"type":25,"value":203}," --output",{"type":20,"tag":141,"props":205,"children":206},{"style":154},[207],{"type":25,"value":208}," podcast.wav",{"type":20,"tag":141,"props":210,"children":211},{"style":160},[212],{"type":25,"value":163},{"type":20,"tag":141,"props":214,"children":216},{"class":143,"line":215},5,[217],{"type":20,"tag":141,"props":218,"children":219},{"style":154},[220],{"type":25,"value":221}," \"https://www.youtube.com/watch?v=CoUN690wSYQ\"\n",{"type":20,"tag":21,"props":223,"children":224},{},[225,227,232],{"type":25,"value":226},"This file has a 44.1 kHz sample rate, and ",{"type":20,"tag":92,"props":228,"children":230},{"className":229},[],[231],{"type":25,"value":12},{"type":25,"value":233}," expects 16 kHz, so let's go ahead and convert that.",{"type":20,"tag":131,"props":235,"children":237},{"code":236,"language":134,"meta":7,"className":135,"style":7}," $ file podcast.wav\npodcast.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz\n\n $ ffmpeg -i podcast.wav -ar 16000 podcast-16khz.wav\n\n $ file podcast-16khz.wav\npodcast-16khz.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 16000 Hz\n\n# NOTE: it looks like it's possible to specify this conversion as a post-process as a\n# flag to the `youtube-dl` command -- I will explore this further next time...\n# youtube-dl --extract-audio --audio-quality 0 --audio-format mp3 --postprocessor-args \"-ar 44100\" %dl%\n",[238],{"type":20,"tag":92,"props":239,"children":240},{"__ignoreMap":7},[241,258,277,286,322,329,345,363,371,381,390],{"type":20,"tag":141,"props":242,"children":243},{"class":143,"line":144},[244,248,253],{"type":20,"tag":141,"props":245,"children":246},{"style":148},[247],{"type":25,"value":151},{"type":20,"tag":141,"props":249,"children":250},{"style":154},[251],{"type":25,"value":252}," file",{"type":20,"tag":141,"props":254,"children":255},{"style":154},[256],{"type":25,"value":257}," podcast.wav\n",{"type":20,"tag":141,"props":259,"children":260},{"class":143,"line":166},[261,266,271],{"type":20,"tag":141,"props":262,"children":263},{"style":148},[264],{"type":25,"value":265},"podcast.wav:",{"type":20,"tag":141,"props":267,"children":268},{"style":154},[269],{"type":25,"value":270}," RIFF",{"type":20,"tag":141,"props":272,"children":274},{"style":273},"--shiki-default:#24292E",[275],{"type":25,"value":276}," (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz\n",{"type":20,"tag":141,"props":278,"children":279},{"class":143,"line":179},[280],{"type":20,"tag":141,"props":281,"children":283},{"emptyLinePlaceholder":282},true,[284],{"type":25,"value":285},"\n",{"type":20,"tag":141,"props":287,"children":288},{"class":143,"line":197},[289,293,298,303,307,312,317],{"type":20,"tag":141,"props":290,"children":291},{"style":148},[292],{"type":25,"value":151},{"type":20,"tag":141,"props":294,"children":295},{"style":154},[296],{"type":25,"value":297}," ffmpeg",{"type":20,"tag":141,"props":299,"children":300},{"style":160},[301],{"type":25,"value":302}," -i",{"type":20,"tag":141,"props":304,"children":305},{"style":154},[306],{"type":25,"value":208},{"type":20,"tag":141,"props":308,"children":309},{"style":160},[310],{"type":25,"value":311}," -ar",{"type":20,"tag":141,"props":313,"children":314},{"style":160},[315],{"type":25,"value":316}," 16000",{"type":20,"tag":141,"props":318,"children":319},{"style":154},[320],{"type":25,"value":321}," podcast-16khz.wav\n",{"type":20,"tag":141,"props":323,"children":324},{"class":143,"line":215},[325],{"type":20,"tag":141,"props":326,"children":327},{"emptyLinePlaceholder":282},[328],{"type":25,"value":285},{"type":20,"tag":141,"props":330,"children":332},{"class":143,"line":331},6,[333,337,341],{"type":20,"tag":141,"props":334,"children":335},{"style":148},[336],{"type":25,"value":151},{"type":20,"tag":141,"props":338,"children":339},{"style":154},[340],{"type":25,"value":252},{"type":20,"tag":141,"props":342,"children":343},{"style":154},[344],{"type":25,"value":321},{"type":20,"tag":141,"props":346,"children":348},{"class":143,"line":347},7,[349,354,358],{"type":20,"tag":141,"props":350,"children":351},{"style":148},[352],{"type":25,"value":353},"podcast-16khz.wav:",{"type":20,"tag":141,"props":355,"children":356},{"style":154},[357],{"type":25,"value":270},{"type":20,"tag":141,"props":359,"children":360},{"style":273},[361],{"type":25,"value":362}," (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 16000 Hz\n",{"type":20,"tag":141,"props":364,"children":366},{"class":143,"line":365},8,[367],{"type":20,"tag":141,"props":368,"children":369},{"emptyLinePlaceholder":282},[370],{"type":25,"value":285},{"type":20,"tag":141,"props":372,"children":374},{"class":143,"line":373},9,[375],{"type":20,"tag":141,"props":376,"children":378},{"style":377},"--shiki-default:#6A737D",[379],{"type":25,"value":380},"# NOTE: it looks like it's possible to specify this conversion as a post-process as a\n",{"type":20,"tag":141,"props":382,"children":384},{"class":143,"line":383},10,[385],{"type":20,"tag":141,"props":386,"children":387},{"style":377},[388],{"type":25,"value":389},"# flag to the `youtube-dl` command -- I will explore this further next time...\n",{"type":20,"tag":141,"props":391,"children":393},{"class":143,"line":392},11,[394],{"type":20,"tag":141,"props":395,"children":396},{"style":377},[397],{"type":25,"value":398},"# youtube-dl --extract-audio --audio-quality 0 --audio-format mp3 --postprocessor-args \"-ar 44100\" %dl%\n",{"type":20,"tag":80,"props":400,"children":402},{"id":401},"build-whispercpp-transcribe-audio",[403,405,410],{"type":25,"value":404},"Build ",{"type":20,"tag":92,"props":406,"children":408},{"className":407},[],[409],{"type":25,"value":12},{"type":25,"value":411}," & Transcribe Audio",{"type":20,"tag":21,"props":413,"children":414},{},[415,417,422],{"type":25,"value":416},"Then, let's get the latest version of ",{"type":20,"tag":92,"props":418,"children":420},{"className":419},[],[421],{"type":25,"value":12},{"type":25,"value":423},", download the English Whisper model, and build the example.",{"type":20,"tag":131,"props":425,"children":427},{"code":426,"language":134,"meta":7,"className":135,"style":7},"# Clone the `whisper.cpp` repository\n $ git clone --depth 1 git@github.com:ggerganov/whisper.cpp && cd whisper.cpp\n\n# Download the English Whisper model in `ggml` format\n $ bash ./models/download-ggml-model.sh base.en\n\n# Build the main example\n $ make\n",[428],{"type":20,"tag":92,"props":429,"children":430},{"__ignoreMap":7},[431,439,486,493,501,523,530,538],{"type":20,"tag":141,"props":432,"children":433},{"class":143,"line":144},[434],{"type":20,"tag":141,"props":435,"children":436},{"style":377},[437],{"type":25,"value":438},"# Clone the `whisper.cpp` repository\n",{"type":20,"tag":141,"props":440,"children":441},{"class":143,"line":166},[442,446,451,456,461,466,471,476,481],{"type":20,"tag":141,"props":443,"children":444},{"style":148},[445],{"type":25,"value":151},{"type":20,"tag":141,"props":447,"children":448},{"style":154},[449],{"type":25,"value":450}," git",{"type":20,"tag":141,"props":452,"children":453},{"style":154},[454],{"type":25,"value":455}," clone",{"type":20,"tag":141,"props":457,"children":458},{"style":160},[459],{"type":25,"value":460}," --depth",{"type":20,"tag":141,"props":462,"children":463},{"style":160},[464],{"type":25,"value":465}," 1",{"type":20,"tag":141,"props":467,"children":468},{"style":154},[469],{"type":25,"value":470}," git@github.com:ggerganov/whisper.cpp",{"type":20,"tag":141,"props":472,"children":473},{"style":273},[474],{"type":25,"value":475}," && ",{"type":20,"tag":141,"props":477,"children":478},{"style":160},[479],{"type":25,"value":480},"cd",{"type":20,"tag":141,"props":482,"children":483},{"style":154},[484],{"type":25,"value":485}," whisper.cpp\n",{"type":20,"tag":141,"props":487,"children":488},{"class":143,"line":179},[489],{"type":20,"tag":141,"props":490,"children":491},{"emptyLinePlaceholder":282},[492],{"type":25,"value":285},{"type":20,"tag":141,"props":494,"children":495},{"class":143,"line":197},[496],{"type":20,"tag":141,"props":497,"children":498},{"style":377},[499],{"type":25,"value":500},"# Download the English Whisper model in `ggml` format\n",{"type":20,"tag":141,"props":502,"children":503},{"class":143,"line":215},[504,508,513,518],{"type":20,"tag":141,"props":505,"children":506},{"style":148},[507],{"type":25,"value":151},{"type":20,"tag":141,"props":509,"children":510},{"style":154},[511],{"type":25,"value":512}," bash",{"type":20,"tag":141,"props":514,"children":515},{"style":154},[516],{"type":25,"value":517}," ./models/download-ggml-model.sh",{"type":20,"tag":141,"props":519,"children":520},{"style":154},[521],{"type":25,"value":522}," base.en\n",{"type":20,"tag":141,"props":524,"children":525},{"class":143,"line":331},[526],{"type":20,"tag":141,"props":527,"children":528},{"emptyLinePlaceholder":282},[529],{"type":25,"value":285},{"type":20,"tag":141,"props":531,"children":532},{"class":143,"line":347},[533],{"type":20,"tag":141,"props":534,"children":535},{"style":377},[536],{"type":25,"value":537},"# Build the main example\n",{"type":20,"tag":141,"props":539,"children":540},{"class":143,"line":365},[541,545],{"type":20,"tag":141,"props":542,"children":543},{"style":148},[544],{"type":25,"value":151},{"type":20,"tag":141,"props":546,"children":547},{"style":154},[548],{"type":25,"value":549}," make\n",{"type":20,"tag":21,"props":551,"children":552},{},[553],{"type":25,"value":554},"And finally, let's transcribe that podcast!",{"type":20,"tag":131,"props":556,"children":558},{"code":557,"language":134,"meta":7,"className":135,"style":7}," $ ./main \\\n -m ~/workspace/whisper.cpp/models/ggml-base.en.bin \\\n -f ~/Downloads/podcast-16khz.wav \\\n --output-vtt \\\n --output-file out\n\n# whisper_print_timings: load time = 114.71 ms\n# whisper_print_timings: fallbacks = 0 p / 0 h\n# whisper_print_timings: mel time = 692.20 ms\n# whisper_print_timings: sample time = 22278.10 ms / 27893 runs ( 0.80 ms per run)\n# whisper_print_timings: encode time = 10000.75 ms / 55 runs ( 181.83 ms per run)\n# whisper_print_timings: decode time = 331.77 ms / 54 runs ( 6.14 ms per run)\n# whisper_print_timings: batchd time = 45236.73 ms / 27566 runs ( 1.64 ms per run)\n# whisper_print_timings: prompt time = 1921.90 ms / 11832 runs ( 0.16 ms per run)\n# whisper_print_timings: total time = 80709.54 ms\n",[559],{"type":20,"tag":92,"props":560,"children":561},{"__ignoreMap":7},[562,578,595,612,624,637,644,652,660,668,676,684,693,702,711],{"type":20,"tag":141,"props":563,"children":564},{"class":143,"line":144},[565,569,574],{"type":20,"tag":141,"props":566,"children":567},{"style":148},[568],{"type":25,"value":151},{"type":20,"tag":141,"props":570,"children":571},{"style":154},[572],{"type":25,"value":573}," ./main",{"type":20,"tag":141,"props":575,"children":576},{"style":160},[577],{"type":25,"value":163},{"type":20,"tag":141,"props":579,"children":580},{"class":143,"line":166},[581,586,591],{"type":20,"tag":141,"props":582,"children":583},{"style":160},[584],{"type":25,"value":585}," -m",{"type":20,"tag":141,"props":587,"children":588},{"style":154},[589],{"type":25,"value":590}," ~/workspace/whisper.cpp/models/ggml-base.en.bin",{"type":20,"tag":141,"props":592,"children":593},{"style":160},[594],{"type":25,"value":163},{"type":20,"tag":141,"props":596,"children":597},{"class":143,"line":179},[598,603,608],{"type":20,"tag":141,"props":599,"children":600},{"style":160},[601],{"type":25,"value":602}," -f",{"type":20,"tag":141,"props":604,"children":605},{"style":154},[606],{"type":25,"value":607}," ~/Downloads/podcast-16khz.wav",{"type":20,"tag":141,"props":609,"children":610},{"style":160},[611],{"type":25,"value":163},{"type":20,"tag":141,"props":613,"children":614},{"class":143,"line":197},[615,620],{"type":20,"tag":141,"props":616,"children":617},{"style":160},[618],{"type":25,"value":619}," --output-vtt",{"type":20,"tag":141,"props":621,"children":622},{"style":160},[623],{"type":25,"value":163},{"type":20,"tag":141,"props":625,"children":626},{"class":143,"line":215},[627,632],{"type":20,"tag":141,"props":628,"children":629},{"style":160},[630],{"type":25,"value":631}," --output-file",{"type":20,"tag":141,"props":633,"children":634},{"style":154},[635],{"type":25,"value":636}," out\n",{"type":20,"tag":141,"props":638,"children":639},{"class":143,"line":331},[640],{"type":20,"tag":141,"props":641,"children":642},{"emptyLinePlaceholder":282},[643],{"type":25,"value":285},{"type":20,"tag":141,"props":645,"children":646},{"class":143,"line":347},[647],{"type":20,"tag":141,"props":648,"children":649},{"style":377},[650],{"type":25,"value":651},"# whisper_print_timings: load time = 114.71 ms\n",{"type":20,"tag":141,"props":653,"children":654},{"class":143,"line":365},[655],{"type":20,"tag":141,"props":656,"children":657},{"style":377},[658],{"type":25,"value":659},"# whisper_print_timings: fallbacks = 0 p / 0 h\n",{"type":20,"tag":141,"props":661,"children":662},{"class":143,"line":373},[663],{"type":20,"tag":141,"props":664,"children":665},{"style":377},[666],{"type":25,"value":667},"# whisper_print_timings: mel time = 692.20 ms\n",{"type":20,"tag":141,"props":669,"children":670},{"class":143,"line":383},[671],{"type":20,"tag":141,"props":672,"children":673},{"style":377},[674],{"type":25,"value":675},"# whisper_print_timings: sample time = 22278.10 ms / 27893 runs ( 0.80 ms per run)\n",{"type":20,"tag":141,"props":677,"children":678},{"class":143,"line":392},[679],{"type":20,"tag":141,"props":680,"children":681},{"style":377},[682],{"type":25,"value":683},"# whisper_print_timings: encode time = 10000.75 ms / 55 runs ( 181.83 ms per run)\n",{"type":20,"tag":141,"props":685,"children":687},{"class":143,"line":686},12,[688],{"type":20,"tag":141,"props":689,"children":690},{"style":377},[691],{"type":25,"value":692},"# whisper_print_timings: decode time = 331.77 ms / 54 runs ( 6.14 ms per run)\n",{"type":20,"tag":141,"props":694,"children":696},{"class":143,"line":695},13,[697],{"type":20,"tag":141,"props":698,"children":699},{"style":377},[700],{"type":25,"value":701},"# whisper_print_timings: batchd time = 45236.73 ms / 27566 runs ( 1.64 ms per run)\n",{"type":20,"tag":141,"props":703,"children":705},{"class":143,"line":704},14,[706],{"type":20,"tag":141,"props":707,"children":708},{"style":377},[709],{"type":25,"value":710},"# whisper_print_timings: prompt time = 1921.90 ms / 11832 runs ( 0.16 ms per run)\n",{"type":20,"tag":141,"props":712,"children":714},{"class":143,"line":713},15,[715],{"type":20,"tag":141,"props":716,"children":717},{"style":377},[718],{"type":25,"value":719},"# whisper_print_timings: total time = 80709.54 ms\n",{"type":20,"tag":21,"props":721,"children":722},{},[723],{"type":25,"value":724},"A full podcast transcribed in ~80 seconds on an M1 Mac Mini -- not too bad!",{"type":20,"tag":131,"props":726,"children":728},{"code":727},"# out.vtt\n\n00:00:00.000 --> 00:00:06.480\n >> Hi everyone. We recently launched a short engagement feedback survey for the Alter Everything\n\n00:00:06.480 --> 00:00:11.360\n podcast. Click the link in the episode description wherever you're listening to let us know what\n\n00:00:11.360 --> 00:00:16.320\n you think and help us improve our show.\n\n00:00:16.320 --> 00:00:21.200\n Welcome to Alter Everything, a podcast about data science and analytics culture. I'm Megan\n\n00:00:21.200 --> 00:00:26.440\n Dibble and today I'm talking with Nick Schrock, CTO and founder of Dagster Labs. We discussed\n\n00:00:26.440 --> 00:00:31.560\n data engineering trends, challenges in the field, why he started his company, and what\n\n00:00:31.560 --> 00:00:38.960\n makes him excited about the future of data engineering. Let's get started.\n\n00:00:38.960 --> 00:00:42.720\n >> Hi, Nick. It's great to have you on our show today. Thanks for being here.\n\n00:00:42.720 --> 00:00:43.920\n >> Thanks for having me.\n\n00:00:43.920 --> 00:00:48.280\n >> Yeah. Could you start off by giving an introduction to yourself for our listeners?\n\n00:00:48.280 --> 00:00:52.920\n >> Sure. My name is Nick Schrock. I'm the CTO and founder of Dagster Labs. There's the\n\n00:00:52.920 --> 00:00:59.520\n company behind Dagster, which is a data orchestration framework. Prior to doing this, I was an engineer\n\n00:00:59.520 --> 00:01:05.960\n at Facebook from 2009, 2017. While I was there, I found a team called product infrastructure\n\n00:01:05.960 --> 00:01:09.800\n whose goal was to make our application developers more efficient and productive, and a bunch\n\n00:01:09.800 --> 00:01:13.840\n of open source work came out of that actually, one of which was React, which I had nothing\n\n00:01:13.840 --> 00:01:18.040\n to do with, but actually the CEO of Dagster Labs co-created and I personally co-created\n\n00:01:18.040 --> 00:01:22.640\n GraphQL. So as I like to say, Pete and I were present at the creation of the full hipster\n\n00:01:22.640 --> 00:01:28.680\n stack. I moved on to Facebook in 2017, figuring out what to do next, and this data engineering\n\n00:01:28.680 --> 00:01:32.960\n and data orchestration problem really got me hooked actually quite soon after I left,\n\n00:01:32.960 --> 00:01:36.280\n and the rest is history. I'm sure we'll get into that more.\n",[729],{"type":20,"tag":92,"props":730,"children":731},{"__ignoreMap":7},[732],{"type":25,"value":727},{"type":20,"tag":734,"props":735,"children":736},"style",{},[737],{"type":25,"value":738},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":166,"depth":166,"links":740},[741,742],{"id":82,"depth":166,"text":85},{"id":401,"depth":166,"text":743},"Build whisper.cpp & Transcribe Audio","markdown","content:articles:podcast-transcription-whispercpp.md","content","articles/podcast-transcription-whispercpp.md","md",1727638398038] \ No newline at end of file diff --git a/articles/podcast-transcription-whispercpp/index.html b/articles/podcast-transcription-whispercpp/index.html index 14f259bc..7523badd 100644 --- a/articles/podcast-transcription-whispercpp/index.html +++ b/articles/podcast-transcription-whispercpp/index.html @@ -4,33 +4,32 @@ - - + + - - - - + + + + - - + - - - - - - - - - - - - - -

            Easily Transcribe Podcasts with Whisper.cpp

            If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive whisper.cpp project. This high-performance fork of OpenAI's Whisper can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the Alter Everything podcast.

            Obtain Audio File(s)

            First, let's get the wav file from YouTube using the youtube-dl utility. It should be noted that whisper.cpp expects wav filetypes, and this utility defaults to mp3.

             $ youtube-dl \
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +

            Easily Transcribe Podcasts with Whisper.cpp

            If you've ever had the need to transcribe a podcast, lecture, or some other audio recording, it turns out it's surprisingly easy with the extremely impressive whisper.cpp project. This high-performance fork of OpenAI's Whisper can run on all sorts of hardware -- including my M1 Mac Mini. Let's walk through an example from start-to-finish of transcribing an episode of the Alter Everything podcast.

            Obtain Audio File(s)

            First, let's get the wav file from YouTube using the youtube-dl utility. It should be noted that whisper.cpp expects wav filetypes, and this utility defaults to mp3.

             $ youtube-dl \
                 --extract-audio \
                 --audio-format wav \
                 --output podcast.wav \
            @@ -130,5 +129,5 @@
             
             00:01:32.960 --> 00:01:36.280
              and the rest is history. I'm sure we'll get into that more.
            -
            - \ No newline at end of file +
            + \ No newline at end of file diff --git a/articles/quick-tip-rerunning-bash-commands/_payload.json b/articles/quick-tip-rerunning-bash-commands/_payload.json index 786a3a29..0364c6af 100644 --- a/articles/quick-tip-rerunning-bash-commands/_payload.json +++ b/articles/quick-tip-rerunning-bash-commands/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":647},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"draft":6,"tags":11,"categories":14,"excerpt":16,"body":36,"_type":641,"_id":642,"_source":643,"_file":644,"_stem":645,"_extension":646},"/articles/quick-tip-rerunning-bash-commands","articles",false,"","Tip: Re-running Bash Commands","Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use sudo for a command that requires\nroot privileges.","2021-09-22",[12,13],"tip","bash",[15],"tips",{"type":17,"children":18},"root",[19],{"type":20,"tag":21,"props":22,"children":23},"element","p",{},[24,27,34],{"type":25,"value":26},"text","Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use ",{"type":20,"tag":28,"props":29,"children":31},"code",{"className":30},[],[32],{"type":25,"value":33},"sudo",{"type":25,"value":35}," for a command that requires\nroot privileges.",{"type":17,"children":37,"toc":639},[38,48,134,161,245,250,279,381,409,463,476,511,530,572,599,603,633],{"type":20,"tag":21,"props":39,"children":40},{},[41,42,47],{"type":25,"value":26},{"type":20,"tag":28,"props":43,"children":45},{"className":44},[],[46],{"type":25,"value":33},{"type":25,"value":35},{"type":20,"tag":49,"props":50,"children":53},"pre",{"className":51,"code":52,"language":13,"meta":7,"style":7},"language-bash shiki shiki-themes github-light","$ pacman -Syu\nerror: you cannot perform this operation unless you are root.\n",[54],{"type":20,"tag":28,"props":55,"children":56},{"__ignoreMap":7},[57,81],{"type":20,"tag":58,"props":59,"children":62},"span",{"class":60,"line":61},"line",1,[63,69,75],{"type":20,"tag":58,"props":64,"children":66},{"style":65},"--shiki-default:#6F42C1",[67],{"type":25,"value":68},"$",{"type":20,"tag":58,"props":70,"children":72},{"style":71},"--shiki-default:#032F62",[73],{"type":25,"value":74}," pacman",{"type":20,"tag":58,"props":76,"children":78},{"style":77},"--shiki-default:#005CC5",[79],{"type":25,"value":80}," -Syu\n",{"type":20,"tag":58,"props":82,"children":84},{"class":60,"line":83},2,[85,90,95,100,105,110,115,120,124,129],{"type":20,"tag":58,"props":86,"children":87},{"style":65},[88],{"type":25,"value":89},"error:",{"type":20,"tag":58,"props":91,"children":92},{"style":71},[93],{"type":25,"value":94}," you",{"type":20,"tag":58,"props":96,"children":97},{"style":71},[98],{"type":25,"value":99}," cannot",{"type":20,"tag":58,"props":101,"children":102},{"style":71},[103],{"type":25,"value":104}," perform",{"type":20,"tag":58,"props":106,"children":107},{"style":71},[108],{"type":25,"value":109}," this",{"type":20,"tag":58,"props":111,"children":112},{"style":71},[113],{"type":25,"value":114}," operation",{"type":20,"tag":58,"props":116,"children":117},{"style":71},[118],{"type":25,"value":119}," unless",{"type":20,"tag":58,"props":121,"children":122},{"style":71},[123],{"type":25,"value":94},{"type":20,"tag":58,"props":125,"children":126},{"style":71},[127],{"type":25,"value":128}," are",{"type":20,"tag":58,"props":130,"children":131},{"style":71},[132],{"type":25,"value":133}," root.\n",{"type":20,"tag":21,"props":135,"children":136},{},[137,139,145,147,152,154,159],{"type":25,"value":138},"Well, I have good news for you -- you can easily re-issue a command with the\n",{"type":20,"tag":28,"props":140,"children":142},{"className":141},[],[143],{"type":25,"value":144},"!!",{"type":25,"value":146}," designator! Simply type ",{"type":20,"tag":28,"props":148,"children":150},{"className":149},[],[151],{"type":25,"value":33},{"type":25,"value":153}," followed by ",{"type":20,"tag":28,"props":155,"children":157},{"className":156},[],[158],{"type":25,"value":144},{"type":25,"value":160}," and you're good to go.",{"type":20,"tag":49,"props":162,"children":164},{"className":51,"code":163,"language":13,"meta":7,"style":7},"$ sudo !!\nsudo pacman -Syu\n[sudo] password for colton:\n:: Synchronizing package databases...\n",[165],{"type":20,"tag":28,"props":166,"children":167},{"__ignoreMap":7},[168,185,200,221],{"type":20,"tag":58,"props":169,"children":170},{"class":60,"line":61},[171,175,180],{"type":20,"tag":58,"props":172,"children":173},{"style":65},[174],{"type":25,"value":68},{"type":20,"tag":58,"props":176,"children":177},{"style":71},[178],{"type":25,"value":179}," sudo",{"type":20,"tag":58,"props":181,"children":182},{"style":71},[183],{"type":25,"value":184}," !!\n",{"type":20,"tag":58,"props":186,"children":187},{"class":60,"line":83},[188,192,196],{"type":20,"tag":58,"props":189,"children":190},{"style":65},[191],{"type":25,"value":33},{"type":20,"tag":58,"props":193,"children":194},{"style":71},[195],{"type":25,"value":74},{"type":20,"tag":58,"props":197,"children":198},{"style":77},[199],{"type":25,"value":80},{"type":20,"tag":58,"props":201,"children":203},{"class":60,"line":202},3,[204,210,216],{"type":20,"tag":58,"props":205,"children":207},{"style":206},"--shiki-default:#24292E",[208],{"type":25,"value":209},"[sudo] password ",{"type":20,"tag":58,"props":211,"children":213},{"style":212},"--shiki-default:#D73A49",[214],{"type":25,"value":215},"for",{"type":20,"tag":58,"props":217,"children":218},{"style":206},[219],{"type":25,"value":220}," colton:\n",{"type":20,"tag":58,"props":222,"children":224},{"class":60,"line":223},4,[225,230,235,240],{"type":20,"tag":58,"props":226,"children":227},{"style":77},[228],{"type":25,"value":229},"::",{"type":20,"tag":58,"props":231,"children":232},{"style":71},[233],{"type":25,"value":234}," Synchronizing",{"type":20,"tag":58,"props":236,"children":237},{"style":71},[238],{"type":25,"value":239}," package",{"type":20,"tag":58,"props":241,"children":242},{"style":71},[243],{"type":25,"value":244}," databases...\n",{"type":20,"tag":21,"props":246,"children":247},{},[248],{"type":25,"value":249},"--",{"type":20,"tag":21,"props":251,"children":252},{},[253,255,261,263,269,271,277],{"type":25,"value":254},"Commands that are prefixed with a bang, ",{"type":20,"tag":28,"props":256,"children":258},{"className":257},[],[259],{"type":25,"value":260},"!",{"type":25,"value":262},", are considered ",{"type":20,"tag":264,"props":265,"children":266},"em",{},[267],{"type":25,"value":268},"Event\nDesignators,",{"type":25,"value":270}," and are references to your command-line history. You can take a\nlook at your history with the ",{"type":20,"tag":28,"props":272,"children":274},{"className":273},[],[275],{"type":25,"value":276},"history",{"type":25,"value":278}," command.",{"type":20,"tag":49,"props":280,"children":282},{"className":51,"code":281,"language":13,"meta":7,"style":7},"$ history\n 1021 touch hello_world.txt\n 1022 ls\n 1023 echo \"Here we go again!\"\n 1024 find . -name *.py\n",[283],{"type":20,"tag":28,"props":284,"children":285},{"__ignoreMap":7},[286,298,316,329,347],{"type":20,"tag":58,"props":287,"children":288},{"class":60,"line":61},[289,293],{"type":20,"tag":58,"props":290,"children":291},{"style":65},[292],{"type":25,"value":68},{"type":20,"tag":58,"props":294,"children":295},{"style":71},[296],{"type":25,"value":297}," history\n",{"type":20,"tag":58,"props":299,"children":300},{"class":60,"line":83},[301,306,311],{"type":20,"tag":58,"props":302,"children":303},{"style":65},[304],{"type":25,"value":305}," 1021",{"type":20,"tag":58,"props":307,"children":308},{"style":71},[309],{"type":25,"value":310}," touch",{"type":20,"tag":58,"props":312,"children":313},{"style":71},[314],{"type":25,"value":315}," hello_world.txt\n",{"type":20,"tag":58,"props":317,"children":318},{"class":60,"line":202},[319,324],{"type":20,"tag":58,"props":320,"children":321},{"style":65},[322],{"type":25,"value":323}," 1022",{"type":20,"tag":58,"props":325,"children":326},{"style":71},[327],{"type":25,"value":328}," ls\n",{"type":20,"tag":58,"props":330,"children":331},{"class":60,"line":223},[332,337,342],{"type":20,"tag":58,"props":333,"children":334},{"style":65},[335],{"type":25,"value":336}," 1023",{"type":20,"tag":58,"props":338,"children":339},{"style":71},[340],{"type":25,"value":341}," echo",{"type":20,"tag":58,"props":343,"children":344},{"style":71},[345],{"type":25,"value":346}," \"Here we go again!\"\n",{"type":20,"tag":58,"props":348,"children":350},{"class":60,"line":349},5,[351,356,361,366,371,376],{"type":20,"tag":58,"props":352,"children":353},{"style":65},[354],{"type":25,"value":355}," 1024",{"type":20,"tag":58,"props":357,"children":358},{"style":71},[359],{"type":25,"value":360}," find",{"type":20,"tag":58,"props":362,"children":363},{"style":71},[364],{"type":25,"value":365}," .",{"type":20,"tag":58,"props":367,"children":368},{"style":77},[369],{"type":25,"value":370}," -name",{"type":20,"tag":58,"props":372,"children":373},{"style":77},[374],{"type":25,"value":375}," *",{"type":20,"tag":58,"props":377,"children":378},{"style":71},[379],{"type":25,"value":380},".py\n",{"type":20,"tag":21,"props":382,"children":383},{},[384,386,391,393,399,401,407],{"type":25,"value":385},"There are many ways to use ",{"type":20,"tag":28,"props":387,"children":389},{"className":388},[],[390],{"type":25,"value":260},{"type":25,"value":392}," in your shell. For example, if you wanted to\nre-issue a specific command in your history, you could use ",{"type":20,"tag":28,"props":394,"children":396},{"className":395},[],[397],{"type":25,"value":398},"!n",{"type":25,"value":400}," where ",{"type":20,"tag":28,"props":402,"children":404},{"className":403},[],[405],{"type":25,"value":406},"n",{"type":25,"value":408}," is\nthe number next to the command in your history.",{"type":20,"tag":49,"props":410,"children":412},{"className":51,"code":411,"language":13,"meta":7,"style":7},"$ !1023\necho \"Here we go again!\"\nHere we go again!\n",[413],{"type":20,"tag":28,"props":414,"children":415},{"__ignoreMap":7},[416,428,440],{"type":20,"tag":58,"props":417,"children":418},{"class":60,"line":61},[419,423],{"type":20,"tag":58,"props":420,"children":421},{"style":65},[422],{"type":25,"value":68},{"type":20,"tag":58,"props":424,"children":425},{"style":71},[426],{"type":25,"value":427}," !1023\n",{"type":20,"tag":58,"props":429,"children":430},{"class":60,"line":83},[431,436],{"type":20,"tag":58,"props":432,"children":433},{"style":77},[434],{"type":25,"value":435},"echo",{"type":20,"tag":58,"props":437,"children":438},{"style":71},[439],{"type":25,"value":346},{"type":20,"tag":58,"props":441,"children":442},{"class":60,"line":202},[443,448,453,458],{"type":20,"tag":58,"props":444,"children":445},{"style":65},[446],{"type":25,"value":447},"Here",{"type":20,"tag":58,"props":449,"children":450},{"style":71},[451],{"type":25,"value":452}," we",{"type":20,"tag":58,"props":454,"children":455},{"style":71},[456],{"type":25,"value":457}," go",{"type":20,"tag":58,"props":459,"children":460},{"style":71},[461],{"type":25,"value":462}," again!\n",{"type":20,"tag":21,"props":464,"children":465},{},[466,468,474],{"type":25,"value":467},"Or... if you wanted to run the command you issued 4-commands ago, you can use\n",{"type":20,"tag":28,"props":469,"children":471},{"className":470},[],[472],{"type":25,"value":473},"!-4",{"type":25,"value":475},".",{"type":20,"tag":49,"props":477,"children":479},{"className":51,"code":478,"language":13,"meta":7,"style":7},"$ !-4\nls\nhello_world.txt\n",[480],{"type":20,"tag":28,"props":481,"children":482},{"__ignoreMap":7},[483,495,503],{"type":20,"tag":58,"props":484,"children":485},{"class":60,"line":61},[486,490],{"type":20,"tag":58,"props":487,"children":488},{"style":65},[489],{"type":25,"value":68},{"type":20,"tag":58,"props":491,"children":492},{"style":71},[493],{"type":25,"value":494}," !-4\n",{"type":20,"tag":58,"props":496,"children":497},{"class":60,"line":83},[498],{"type":20,"tag":58,"props":499,"children":500},{"style":65},[501],{"type":25,"value":502},"ls\n",{"type":20,"tag":58,"props":504,"children":505},{"class":60,"line":202},[506],{"type":20,"tag":58,"props":507,"children":508},{"style":65},[509],{"type":25,"value":510},"hello_world.txt\n",{"type":20,"tag":21,"props":512,"children":513},{},[514,516,521,523,529],{"type":25,"value":515},"Or... if you wanted to run the last command that started with the string\n",{"type":20,"tag":264,"props":517,"children":518},{},[519],{"type":25,"value":520},"find",{"type":25,"value":522},", you can use ",{"type":20,"tag":28,"props":524,"children":526},{"className":525},[],[527],{"type":25,"value":528},"!find",{"type":25,"value":475},{"type":20,"tag":49,"props":531,"children":533},{"className":51,"code":532,"language":13,"meta":7,"style":7},"$ !find\nfind . -name *.py\n",[534],{"type":20,"tag":28,"props":535,"children":536},{"__ignoreMap":7},[537,549],{"type":20,"tag":58,"props":538,"children":539},{"class":60,"line":61},[540,544],{"type":20,"tag":58,"props":541,"children":542},{"style":65},[543],{"type":25,"value":68},{"type":20,"tag":58,"props":545,"children":546},{"style":71},[547],{"type":25,"value":548}," !find\n",{"type":20,"tag":58,"props":550,"children":551},{"class":60,"line":83},[552,556,560,564,568],{"type":20,"tag":58,"props":553,"children":554},{"style":65},[555],{"type":25,"value":520},{"type":20,"tag":58,"props":557,"children":558},{"style":71},[559],{"type":25,"value":365},{"type":20,"tag":58,"props":561,"children":562},{"style":77},[563],{"type":25,"value":370},{"type":20,"tag":58,"props":565,"children":566},{"style":77},[567],{"type":25,"value":375},{"type":20,"tag":58,"props":569,"children":570},{"style":71},[571],{"type":25,"value":380},{"type":20,"tag":21,"props":573,"children":574},{},[575,577,582,584,589,591,597],{"type":25,"value":576},"Be sure to check out the ",{"type":20,"tag":264,"props":578,"children":579},{},[580],{"type":25,"value":581},"Event Designators",{"type":25,"value":583}," section of the ",{"type":20,"tag":28,"props":585,"children":587},{"className":586},[],[588],{"type":25,"value":13},{"type":25,"value":590}," ",{"type":20,"tag":28,"props":592,"children":594},{"className":593},[],[595],{"type":25,"value":596},"man",{"type":25,"value":598}," pages\nfor more information!",{"type":20,"tag":21,"props":600,"children":601},{},[602],{"type":25,"value":249},{"type":20,"tag":21,"props":604,"children":605},{},[606,608,617,619,624,626,631],{"type":25,"value":607},"As an aside, for even faster command-line history navigation, be sure to check\nout the excellent ",{"type":20,"tag":609,"props":610,"children":614},"a",{"href":611,"rel":612},"https://github.com/junegunn/fzf",[613],"nofollow",[615],{"type":25,"value":616},"fzf",{"type":25,"value":618}," utility by ",{"type":20,"tag":264,"props":620,"children":621},{},[622],{"type":25,"value":623},"junegunn.",{"type":25,"value":625},"\nOne of the many features of ",{"type":20,"tag":28,"props":627,"children":629},{"className":628},[],[630],{"type":25,"value":616},{"type":25,"value":632}," is browsing and re-issuing commands from your\ncommand-line history with a fuzzy-finder!",{"type":20,"tag":634,"props":635,"children":636},"style",{},[637],{"type":25,"value":638},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":83,"depth":83,"links":640},[],"markdown","content:articles:quick-tip-rerunning-bash-commands.md","content","articles/quick-tip-rerunning-bash-commands.md","articles/quick-tip-rerunning-bash-commands","md",1726174739522] \ No newline at end of file +[{"data":1,"prerenderedAt":646},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"draft":6,"tags":11,"categories":14,"excerpt":16,"body":36,"_type":641,"_id":642,"_source":643,"_file":644,"_extension":645},"/articles/quick-tip-rerunning-bash-commands","articles",false,"","Tip: Re-running Bash Commands","Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use sudo for a command that requires\nroot privileges.","2021-09-22",[12,13],"tip","bash",[15],"tips",{"type":17,"children":18},"root",[19],{"type":20,"tag":21,"props":22,"children":23},"element","p",{},[24,27,34],{"type":25,"value":26},"text","Do you ever find yourself having to re-run a Bash command? I often find this\nhappening to myself when I neglect to use ",{"type":20,"tag":28,"props":29,"children":31},"code",{"className":30},[],[32],{"type":25,"value":33},"sudo",{"type":25,"value":35}," for a command that requires\nroot privileges.",{"type":17,"children":37,"toc":639},[38,48,134,161,245,250,279,381,409,463,476,511,530,572,599,603,633],{"type":20,"tag":21,"props":39,"children":40},{},[41,42,47],{"type":25,"value":26},{"type":20,"tag":28,"props":43,"children":45},{"className":44},[],[46],{"type":25,"value":33},{"type":25,"value":35},{"type":20,"tag":49,"props":50,"children":53},"pre",{"className":51,"code":52,"language":13,"meta":7,"style":7},"language-bash shiki shiki-themes github-light","$ pacman -Syu\nerror: you cannot perform this operation unless you are root.\n",[54],{"type":20,"tag":28,"props":55,"children":56},{"__ignoreMap":7},[57,81],{"type":20,"tag":58,"props":59,"children":62},"span",{"class":60,"line":61},"line",1,[63,69,75],{"type":20,"tag":58,"props":64,"children":66},{"style":65},"--shiki-default:#6F42C1",[67],{"type":25,"value":68},"$",{"type":20,"tag":58,"props":70,"children":72},{"style":71},"--shiki-default:#032F62",[73],{"type":25,"value":74}," pacman",{"type":20,"tag":58,"props":76,"children":78},{"style":77},"--shiki-default:#005CC5",[79],{"type":25,"value":80}," -Syu\n",{"type":20,"tag":58,"props":82,"children":84},{"class":60,"line":83},2,[85,90,95,100,105,110,115,120,124,129],{"type":20,"tag":58,"props":86,"children":87},{"style":65},[88],{"type":25,"value":89},"error:",{"type":20,"tag":58,"props":91,"children":92},{"style":71},[93],{"type":25,"value":94}," you",{"type":20,"tag":58,"props":96,"children":97},{"style":71},[98],{"type":25,"value":99}," cannot",{"type":20,"tag":58,"props":101,"children":102},{"style":71},[103],{"type":25,"value":104}," perform",{"type":20,"tag":58,"props":106,"children":107},{"style":71},[108],{"type":25,"value":109}," this",{"type":20,"tag":58,"props":111,"children":112},{"style":71},[113],{"type":25,"value":114}," operation",{"type":20,"tag":58,"props":116,"children":117},{"style":71},[118],{"type":25,"value":119}," unless",{"type":20,"tag":58,"props":121,"children":122},{"style":71},[123],{"type":25,"value":94},{"type":20,"tag":58,"props":125,"children":126},{"style":71},[127],{"type":25,"value":128}," are",{"type":20,"tag":58,"props":130,"children":131},{"style":71},[132],{"type":25,"value":133}," root.\n",{"type":20,"tag":21,"props":135,"children":136},{},[137,139,145,147,152,154,159],{"type":25,"value":138},"Well, I have good news for you -- you can easily re-issue a command with the\n",{"type":20,"tag":28,"props":140,"children":142},{"className":141},[],[143],{"type":25,"value":144},"!!",{"type":25,"value":146}," designator! Simply type ",{"type":20,"tag":28,"props":148,"children":150},{"className":149},[],[151],{"type":25,"value":33},{"type":25,"value":153}," followed by ",{"type":20,"tag":28,"props":155,"children":157},{"className":156},[],[158],{"type":25,"value":144},{"type":25,"value":160}," and you're good to go.",{"type":20,"tag":49,"props":162,"children":164},{"className":51,"code":163,"language":13,"meta":7,"style":7},"$ sudo !!\nsudo pacman -Syu\n[sudo] password for colton:\n:: Synchronizing package databases...\n",[165],{"type":20,"tag":28,"props":166,"children":167},{"__ignoreMap":7},[168,185,200,221],{"type":20,"tag":58,"props":169,"children":170},{"class":60,"line":61},[171,175,180],{"type":20,"tag":58,"props":172,"children":173},{"style":65},[174],{"type":25,"value":68},{"type":20,"tag":58,"props":176,"children":177},{"style":71},[178],{"type":25,"value":179}," sudo",{"type":20,"tag":58,"props":181,"children":182},{"style":71},[183],{"type":25,"value":184}," !!\n",{"type":20,"tag":58,"props":186,"children":187},{"class":60,"line":83},[188,192,196],{"type":20,"tag":58,"props":189,"children":190},{"style":65},[191],{"type":25,"value":33},{"type":20,"tag":58,"props":193,"children":194},{"style":71},[195],{"type":25,"value":74},{"type":20,"tag":58,"props":197,"children":198},{"style":77},[199],{"type":25,"value":80},{"type":20,"tag":58,"props":201,"children":203},{"class":60,"line":202},3,[204,210,216],{"type":20,"tag":58,"props":205,"children":207},{"style":206},"--shiki-default:#24292E",[208],{"type":25,"value":209},"[sudo] password ",{"type":20,"tag":58,"props":211,"children":213},{"style":212},"--shiki-default:#D73A49",[214],{"type":25,"value":215},"for",{"type":20,"tag":58,"props":217,"children":218},{"style":206},[219],{"type":25,"value":220}," colton:\n",{"type":20,"tag":58,"props":222,"children":224},{"class":60,"line":223},4,[225,230,235,240],{"type":20,"tag":58,"props":226,"children":227},{"style":77},[228],{"type":25,"value":229},"::",{"type":20,"tag":58,"props":231,"children":232},{"style":71},[233],{"type":25,"value":234}," Synchronizing",{"type":20,"tag":58,"props":236,"children":237},{"style":71},[238],{"type":25,"value":239}," package",{"type":20,"tag":58,"props":241,"children":242},{"style":71},[243],{"type":25,"value":244}," databases...\n",{"type":20,"tag":21,"props":246,"children":247},{},[248],{"type":25,"value":249},"--",{"type":20,"tag":21,"props":251,"children":252},{},[253,255,261,263,269,271,277],{"type":25,"value":254},"Commands that are prefixed with a bang, ",{"type":20,"tag":28,"props":256,"children":258},{"className":257},[],[259],{"type":25,"value":260},"!",{"type":25,"value":262},", are considered ",{"type":20,"tag":264,"props":265,"children":266},"em",{},[267],{"type":25,"value":268},"Event\nDesignators,",{"type":25,"value":270}," and are references to your command-line history. You can take a\nlook at your history with the ",{"type":20,"tag":28,"props":272,"children":274},{"className":273},[],[275],{"type":25,"value":276},"history",{"type":25,"value":278}," command.",{"type":20,"tag":49,"props":280,"children":282},{"className":51,"code":281,"language":13,"meta":7,"style":7},"$ history\n 1021 touch hello_world.txt\n 1022 ls\n 1023 echo \"Here we go again!\"\n 1024 find . -name *.py\n",[283],{"type":20,"tag":28,"props":284,"children":285},{"__ignoreMap":7},[286,298,316,329,347],{"type":20,"tag":58,"props":287,"children":288},{"class":60,"line":61},[289,293],{"type":20,"tag":58,"props":290,"children":291},{"style":65},[292],{"type":25,"value":68},{"type":20,"tag":58,"props":294,"children":295},{"style":71},[296],{"type":25,"value":297}," history\n",{"type":20,"tag":58,"props":299,"children":300},{"class":60,"line":83},[301,306,311],{"type":20,"tag":58,"props":302,"children":303},{"style":65},[304],{"type":25,"value":305}," 1021",{"type":20,"tag":58,"props":307,"children":308},{"style":71},[309],{"type":25,"value":310}," touch",{"type":20,"tag":58,"props":312,"children":313},{"style":71},[314],{"type":25,"value":315}," hello_world.txt\n",{"type":20,"tag":58,"props":317,"children":318},{"class":60,"line":202},[319,324],{"type":20,"tag":58,"props":320,"children":321},{"style":65},[322],{"type":25,"value":323}," 1022",{"type":20,"tag":58,"props":325,"children":326},{"style":71},[327],{"type":25,"value":328}," ls\n",{"type":20,"tag":58,"props":330,"children":331},{"class":60,"line":223},[332,337,342],{"type":20,"tag":58,"props":333,"children":334},{"style":65},[335],{"type":25,"value":336}," 1023",{"type":20,"tag":58,"props":338,"children":339},{"style":71},[340],{"type":25,"value":341}," echo",{"type":20,"tag":58,"props":343,"children":344},{"style":71},[345],{"type":25,"value":346}," \"Here we go again!\"\n",{"type":20,"tag":58,"props":348,"children":350},{"class":60,"line":349},5,[351,356,361,366,371,376],{"type":20,"tag":58,"props":352,"children":353},{"style":65},[354],{"type":25,"value":355}," 1024",{"type":20,"tag":58,"props":357,"children":358},{"style":71},[359],{"type":25,"value":360}," find",{"type":20,"tag":58,"props":362,"children":363},{"style":71},[364],{"type":25,"value":365}," .",{"type":20,"tag":58,"props":367,"children":368},{"style":77},[369],{"type":25,"value":370}," -name",{"type":20,"tag":58,"props":372,"children":373},{"style":77},[374],{"type":25,"value":375}," *",{"type":20,"tag":58,"props":377,"children":378},{"style":71},[379],{"type":25,"value":380},".py\n",{"type":20,"tag":21,"props":382,"children":383},{},[384,386,391,393,399,401,407],{"type":25,"value":385},"There are many ways to use ",{"type":20,"tag":28,"props":387,"children":389},{"className":388},[],[390],{"type":25,"value":260},{"type":25,"value":392}," in your shell. For example, if you wanted to\nre-issue a specific command in your history, you could use ",{"type":20,"tag":28,"props":394,"children":396},{"className":395},[],[397],{"type":25,"value":398},"!n",{"type":25,"value":400}," where ",{"type":20,"tag":28,"props":402,"children":404},{"className":403},[],[405],{"type":25,"value":406},"n",{"type":25,"value":408}," is\nthe number next to the command in your history.",{"type":20,"tag":49,"props":410,"children":412},{"className":51,"code":411,"language":13,"meta":7,"style":7},"$ !1023\necho \"Here we go again!\"\nHere we go again!\n",[413],{"type":20,"tag":28,"props":414,"children":415},{"__ignoreMap":7},[416,428,440],{"type":20,"tag":58,"props":417,"children":418},{"class":60,"line":61},[419,423],{"type":20,"tag":58,"props":420,"children":421},{"style":65},[422],{"type":25,"value":68},{"type":20,"tag":58,"props":424,"children":425},{"style":71},[426],{"type":25,"value":427}," !1023\n",{"type":20,"tag":58,"props":429,"children":430},{"class":60,"line":83},[431,436],{"type":20,"tag":58,"props":432,"children":433},{"style":77},[434],{"type":25,"value":435},"echo",{"type":20,"tag":58,"props":437,"children":438},{"style":71},[439],{"type":25,"value":346},{"type":20,"tag":58,"props":441,"children":442},{"class":60,"line":202},[443,448,453,458],{"type":20,"tag":58,"props":444,"children":445},{"style":65},[446],{"type":25,"value":447},"Here",{"type":20,"tag":58,"props":449,"children":450},{"style":71},[451],{"type":25,"value":452}," we",{"type":20,"tag":58,"props":454,"children":455},{"style":71},[456],{"type":25,"value":457}," go",{"type":20,"tag":58,"props":459,"children":460},{"style":71},[461],{"type":25,"value":462}," again!\n",{"type":20,"tag":21,"props":464,"children":465},{},[466,468,474],{"type":25,"value":467},"Or... if you wanted to run the command you issued 4-commands ago, you can use\n",{"type":20,"tag":28,"props":469,"children":471},{"className":470},[],[472],{"type":25,"value":473},"!-4",{"type":25,"value":475},".",{"type":20,"tag":49,"props":477,"children":479},{"className":51,"code":478,"language":13,"meta":7,"style":7},"$ !-4\nls\nhello_world.txt\n",[480],{"type":20,"tag":28,"props":481,"children":482},{"__ignoreMap":7},[483,495,503],{"type":20,"tag":58,"props":484,"children":485},{"class":60,"line":61},[486,490],{"type":20,"tag":58,"props":487,"children":488},{"style":65},[489],{"type":25,"value":68},{"type":20,"tag":58,"props":491,"children":492},{"style":71},[493],{"type":25,"value":494}," !-4\n",{"type":20,"tag":58,"props":496,"children":497},{"class":60,"line":83},[498],{"type":20,"tag":58,"props":499,"children":500},{"style":65},[501],{"type":25,"value":502},"ls\n",{"type":20,"tag":58,"props":504,"children":505},{"class":60,"line":202},[506],{"type":20,"tag":58,"props":507,"children":508},{"style":65},[509],{"type":25,"value":510},"hello_world.txt\n",{"type":20,"tag":21,"props":512,"children":513},{},[514,516,521,523,529],{"type":25,"value":515},"Or... if you wanted to run the last command that started with the string\n",{"type":20,"tag":264,"props":517,"children":518},{},[519],{"type":25,"value":520},"find",{"type":25,"value":522},", you can use ",{"type":20,"tag":28,"props":524,"children":526},{"className":525},[],[527],{"type":25,"value":528},"!find",{"type":25,"value":475},{"type":20,"tag":49,"props":531,"children":533},{"className":51,"code":532,"language":13,"meta":7,"style":7},"$ !find\nfind . -name *.py\n",[534],{"type":20,"tag":28,"props":535,"children":536},{"__ignoreMap":7},[537,549],{"type":20,"tag":58,"props":538,"children":539},{"class":60,"line":61},[540,544],{"type":20,"tag":58,"props":541,"children":542},{"style":65},[543],{"type":25,"value":68},{"type":20,"tag":58,"props":545,"children":546},{"style":71},[547],{"type":25,"value":548}," !find\n",{"type":20,"tag":58,"props":550,"children":551},{"class":60,"line":83},[552,556,560,564,568],{"type":20,"tag":58,"props":553,"children":554},{"style":65},[555],{"type":25,"value":520},{"type":20,"tag":58,"props":557,"children":558},{"style":71},[559],{"type":25,"value":365},{"type":20,"tag":58,"props":561,"children":562},{"style":77},[563],{"type":25,"value":370},{"type":20,"tag":58,"props":565,"children":566},{"style":77},[567],{"type":25,"value":375},{"type":20,"tag":58,"props":569,"children":570},{"style":71},[571],{"type":25,"value":380},{"type":20,"tag":21,"props":573,"children":574},{},[575,577,582,584,589,591,597],{"type":25,"value":576},"Be sure to check out the ",{"type":20,"tag":264,"props":578,"children":579},{},[580],{"type":25,"value":581},"Event Designators",{"type":25,"value":583}," section of the ",{"type":20,"tag":28,"props":585,"children":587},{"className":586},[],[588],{"type":25,"value":13},{"type":25,"value":590}," ",{"type":20,"tag":28,"props":592,"children":594},{"className":593},[],[595],{"type":25,"value":596},"man",{"type":25,"value":598}," pages\nfor more information!",{"type":20,"tag":21,"props":600,"children":601},{},[602],{"type":25,"value":249},{"type":20,"tag":21,"props":604,"children":605},{},[606,608,617,619,624,626,631],{"type":25,"value":607},"As an aside, for even faster command-line history navigation, be sure to check\nout the excellent ",{"type":20,"tag":609,"props":610,"children":614},"a",{"href":611,"rel":612},"https://github.com/junegunn/fzf",[613],"nofollow",[615],{"type":25,"value":616},"fzf",{"type":25,"value":618}," utility by ",{"type":20,"tag":264,"props":620,"children":621},{},[622],{"type":25,"value":623},"junegunn.",{"type":25,"value":625},"\nOne of the many features of ",{"type":20,"tag":28,"props":627,"children":629},{"className":628},[],[630],{"type":25,"value":616},{"type":25,"value":632}," is browsing and re-issuing commands from your\ncommand-line history with a fuzzy-finder!",{"type":20,"tag":634,"props":635,"children":636},"style",{},[637],{"type":25,"value":638},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":83,"depth":83,"links":640},[],"markdown","content:articles:quick-tip-rerunning-bash-commands.md","content","articles/quick-tip-rerunning-bash-commands.md","md",1727638398052] \ No newline at end of file diff --git a/articles/quick-tip-rerunning-bash-commands/index.html b/articles/quick-tip-rerunning-bash-commands/index.html index d7ee8a3c..0f2bf52a 100644 --- a/articles/quick-tip-rerunning-bash-commands/index.html +++ b/articles/quick-tip-rerunning-bash-commands/index.html @@ -4,33 +4,32 @@ - - + + - - - - + + + + - - + - - - - - - - - - - - - - -
            Category

            Tip: Re-running Bash Commands

            Do you ever find yourself having to re-run a Bash command? I often find this + + + + + + + + + + + + + +

            Category

            Tip: Re-running Bash Commands

            Do you ever find yourself having to re-run a Bash command? I often find this happening to myself when I neglect to use sudo for a command that requires root privileges.

            $ pacman -Syu
             error: you cannot perform this operation unless you are root.
            @@ -62,5 +61,5 @@
             for more information!

            --

            As an aside, for even faster command-line history navigation, be sure to check out the excellent fzf utility by junegunn. One of the many features of fzf is browsing and re-issuing commands from your -command-line history with a fuzzy-finder!

            - \ No newline at end of file +command-line history with a fuzzy-finder!

            + \ No newline at end of file diff --git a/articles/reset-ipmi-password-from-host-os/_payload.json b/articles/reset-ipmi-password-from-host-os/_payload.json index be38dc0a..c84e0201 100644 --- a/articles/reset-ipmi-password-from-host-os/_payload.json +++ b/articles/reset-ipmi-password-from-host-os/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":203},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"tags":11,"categories":15,"excerpt":16,"body":26,"_type":197,"_id":198,"_source":199,"_file":200,"_stem":201,"_extension":202},"/articles/reset-ipmi-password-from-host-os","articles",false,"","Reset IPMI Credentials from the Host OS","If you ever find yourself locked out of the Intelligent Platform Management Interface (IPMI) of a server, these\ninstructions will guide your through the process of resetting the credentials to their default values from the host\noperating system.","2021-12-27",[12,13,14],"homelab","supermicro","truenas",[12],{"type":17,"children":18},"root",[19],{"type":20,"tag":21,"props":22,"children":23},"element","p",{},[24],{"type":25,"value":9},"text",{"type":17,"children":27,"toc":194},[28,32,54,67,72,81,100,108,113,118,123,131],{"type":20,"tag":21,"props":29,"children":30},{},[31],{"type":25,"value":9},{"type":20,"tag":21,"props":33,"children":34},{},[35,37,44,46,52],{"type":25,"value":36},"If you are using an operating system like TrueNAS -- good news! It's possible to reset the IPMI password directly from\nthe web interface. This is done by navigating to ",{"type":20,"tag":38,"props":39,"children":41},"code",{"className":40},[],[42],{"type":25,"value":43},"Network > IPMI",{"type":25,"value":45},", and simply entering a new value in the ",{"type":20,"tag":47,"props":48,"children":49},"em",{},[50],{"type":25,"value":51},"IPMI\nPassword Reset",{"type":25,"value":53}," field.",{"type":20,"tag":21,"props":55,"children":56},{},[57,59,65],{"type":25,"value":58},"If you are using some other OS that doesn't have this feature, you can achieve similar results by using the ",{"type":20,"tag":38,"props":60,"children":62},{"className":61},[],[63],{"type":25,"value":64},"ipmitool",{"type":25,"value":66},"\ncommand-line utility.",{"type":20,"tag":21,"props":68,"children":69},{},[70],{"type":25,"value":71},"First, you'll want to determine the user ID associated with the user for whom you'd like to reset the password.",{"type":20,"tag":73,"props":74,"children":76},"pre",{"code":75},"# ipmitool user list\nID Name Callin Link Auth IPMI Msg Channel Priv Limit\n1 true false false Unknown (0x00)\n2 ADMIN true false false Unknown (0x00)\n",[77],{"type":20,"tag":38,"props":78,"children":79},{"__ignoreMap":7},[80],{"type":25,"value":75},{"type":20,"tag":21,"props":82,"children":83},{},[84,86,91,93,98],{"type":25,"value":85},"In this case, we will be resetting the password for ",{"type":20,"tag":47,"props":87,"children":88},{},[89],{"type":25,"value":90},"ADMIN",{"type":25,"value":92}," who has a user ID of ",{"type":20,"tag":47,"props":94,"children":95},{},[96],{"type":25,"value":97},"2",{"type":25,"value":99},". Then we'll assign the new\npassword like so:",{"type":20,"tag":73,"props":101,"children":103},{"code":102},"# ipmitool user set password 2 \u003Cpassword>\n",[104],{"type":20,"tag":38,"props":105,"children":106},{"__ignoreMap":7},[107],{"type":25,"value":102},{"type":20,"tag":21,"props":109,"children":110},{},[111],{"type":25,"value":112},"And you should be good to go!",{"type":20,"tag":21,"props":114,"children":115},{},[116],{"type":25,"value":117},"...",{"type":20,"tag":21,"props":119,"children":120},{},[121],{"type":25,"value":122},"Alternatively, if you'd like to factory reset the baseboard management controller (BMC), which will reset the IPMI\ncredentials to their default value, you can issue the following command.",{"type":20,"tag":73,"props":124,"children":126},{"code":125},"# ipmitool raw 0x3c 0x40\n",[127],{"type":20,"tag":38,"props":128,"children":129},{"__ignoreMap":7},[130],{"type":25,"value":125},{"type":20,"tag":21,"props":132,"children":133},{},[134,136,142,144,150,152,158,159,165,167,176,178,183,185,192],{"type":25,"value":135},"Where ",{"type":20,"tag":38,"props":137,"children":139},{"className":138},[],[140],{"type":25,"value":141},"0x3c",{"type":25,"value":143}," is the ",{"type":20,"tag":38,"props":145,"children":147},{"className":146},[],[148],{"type":25,"value":149},"\u003Cnetfn>",{"type":25,"value":151}," argument, a.k.a. the network function code that defines the functional routing for\nmessages, and ",{"type":20,"tag":38,"props":153,"children":155},{"className":154},[],[156],{"type":25,"value":157},"0x40",{"type":25,"value":143},{"type":20,"tag":38,"props":160,"children":162},{"className":161},[],[163],{"type":25,"value":164},"\u003Ccmd>",{"type":25,"value":166},". According to section 5.1 of the ",{"type":20,"tag":168,"props":169,"children":173},"a",{"href":170,"rel":171},"https://www.intel.com/content/dam/www/public/us/en/documents/product-briefs/ipmi-second-gen-interface-spec-v2-rev1-1.pdf",[172],"nofollow",[174],{"type":25,"value":175},"IPMI interface\nspecification",{"type":25,"value":177},",\n",{"type":20,"tag":47,"props":179,"children":180},{},[181],{"type":25,"value":182},"netfn",{"type":25,"value":184}," codes ranging from 0x30 to 0x3F are reserved for vendor specific functions. I searched around for some\nSupermicro references on these vendor specific network functions without much luck other than various ",{"type":20,"tag":168,"props":186,"children":189},{"href":187,"rel":188},"https://www.supermicro.com/support/faqs/faq.cfm?faq=15448",[172],[190],{"type":25,"value":191},"support\nresponses",{"type":25,"value":193}," on how to reset a device. Bummer!",{"title":7,"searchDepth":195,"depth":195,"links":196},2,[],"markdown","content:articles:reset-ipmi-password-from-host-os.md","content","articles/reset-ipmi-password-from-host-os.md","articles/reset-ipmi-password-from-host-os","md",1726174739520] \ No newline at end of file +[{"data":1,"prerenderedAt":202},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"tags":11,"categories":15,"excerpt":16,"body":26,"_type":197,"_id":198,"_source":199,"_file":200,"_extension":201},"/articles/reset-ipmi-password-from-host-os","articles",false,"","Reset IPMI Credentials from the Host OS","If you ever find yourself locked out of the Intelligent Platform Management Interface (IPMI) of a server, these\ninstructions will guide your through the process of resetting the credentials to their default values from the host\noperating system.","2021-12-27",[12,13,14],"homelab","supermicro","truenas",[12],{"type":17,"children":18},"root",[19],{"type":20,"tag":21,"props":22,"children":23},"element","p",{},[24],{"type":25,"value":9},"text",{"type":17,"children":27,"toc":194},[28,32,54,67,72,81,100,108,113,118,123,131],{"type":20,"tag":21,"props":29,"children":30},{},[31],{"type":25,"value":9},{"type":20,"tag":21,"props":33,"children":34},{},[35,37,44,46,52],{"type":25,"value":36},"If you are using an operating system like TrueNAS -- good news! It's possible to reset the IPMI password directly from\nthe web interface. This is done by navigating to ",{"type":20,"tag":38,"props":39,"children":41},"code",{"className":40},[],[42],{"type":25,"value":43},"Network > IPMI",{"type":25,"value":45},", and simply entering a new value in the ",{"type":20,"tag":47,"props":48,"children":49},"em",{},[50],{"type":25,"value":51},"IPMI\nPassword Reset",{"type":25,"value":53}," field.",{"type":20,"tag":21,"props":55,"children":56},{},[57,59,65],{"type":25,"value":58},"If you are using some other OS that doesn't have this feature, you can achieve similar results by using the ",{"type":20,"tag":38,"props":60,"children":62},{"className":61},[],[63],{"type":25,"value":64},"ipmitool",{"type":25,"value":66},"\ncommand-line utility.",{"type":20,"tag":21,"props":68,"children":69},{},[70],{"type":25,"value":71},"First, you'll want to determine the user ID associated with the user for whom you'd like to reset the password.",{"type":20,"tag":73,"props":74,"children":76},"pre",{"code":75},"# ipmitool user list\nID Name Callin Link Auth IPMI Msg Channel Priv Limit\n1 true false false Unknown (0x00)\n2 ADMIN true false false Unknown (0x00)\n",[77],{"type":20,"tag":38,"props":78,"children":79},{"__ignoreMap":7},[80],{"type":25,"value":75},{"type":20,"tag":21,"props":82,"children":83},{},[84,86,91,93,98],{"type":25,"value":85},"In this case, we will be resetting the password for ",{"type":20,"tag":47,"props":87,"children":88},{},[89],{"type":25,"value":90},"ADMIN",{"type":25,"value":92}," who has a user ID of ",{"type":20,"tag":47,"props":94,"children":95},{},[96],{"type":25,"value":97},"2",{"type":25,"value":99},". Then we'll assign the new\npassword like so:",{"type":20,"tag":73,"props":101,"children":103},{"code":102},"# ipmitool user set password 2 \u003Cpassword>\n",[104],{"type":20,"tag":38,"props":105,"children":106},{"__ignoreMap":7},[107],{"type":25,"value":102},{"type":20,"tag":21,"props":109,"children":110},{},[111],{"type":25,"value":112},"And you should be good to go!",{"type":20,"tag":21,"props":114,"children":115},{},[116],{"type":25,"value":117},"...",{"type":20,"tag":21,"props":119,"children":120},{},[121],{"type":25,"value":122},"Alternatively, if you'd like to factory reset the baseboard management controller (BMC), which will reset the IPMI\ncredentials to their default value, you can issue the following command.",{"type":20,"tag":73,"props":124,"children":126},{"code":125},"# ipmitool raw 0x3c 0x40\n",[127],{"type":20,"tag":38,"props":128,"children":129},{"__ignoreMap":7},[130],{"type":25,"value":125},{"type":20,"tag":21,"props":132,"children":133},{},[134,136,142,144,150,152,158,159,165,167,176,178,183,185,192],{"type":25,"value":135},"Where ",{"type":20,"tag":38,"props":137,"children":139},{"className":138},[],[140],{"type":25,"value":141},"0x3c",{"type":25,"value":143}," is the ",{"type":20,"tag":38,"props":145,"children":147},{"className":146},[],[148],{"type":25,"value":149},"\u003Cnetfn>",{"type":25,"value":151}," argument, a.k.a. the network function code that defines the functional routing for\nmessages, and ",{"type":20,"tag":38,"props":153,"children":155},{"className":154},[],[156],{"type":25,"value":157},"0x40",{"type":25,"value":143},{"type":20,"tag":38,"props":160,"children":162},{"className":161},[],[163],{"type":25,"value":164},"\u003Ccmd>",{"type":25,"value":166},". According to section 5.1 of the ",{"type":20,"tag":168,"props":169,"children":173},"a",{"href":170,"rel":171},"https://www.intel.com/content/dam/www/public/us/en/documents/product-briefs/ipmi-second-gen-interface-spec-v2-rev1-1.pdf",[172],"nofollow",[174],{"type":25,"value":175},"IPMI interface\nspecification",{"type":25,"value":177},",\n",{"type":20,"tag":47,"props":179,"children":180},{},[181],{"type":25,"value":182},"netfn",{"type":25,"value":184}," codes ranging from 0x30 to 0x3F are reserved for vendor specific functions. I searched around for some\nSupermicro references on these vendor specific network functions without much luck other than various ",{"type":20,"tag":168,"props":186,"children":189},{"href":187,"rel":188},"https://www.supermicro.com/support/faqs/faq.cfm?faq=15448",[172],[190],{"type":25,"value":191},"support\nresponses",{"type":25,"value":193}," on how to reset a device. Bummer!",{"title":7,"searchDepth":195,"depth":195,"links":196},2,[],"markdown","content:articles:reset-ipmi-password-from-host-os.md","content","articles/reset-ipmi-password-from-host-os.md","md",1727638398050] \ No newline at end of file diff --git a/articles/reset-ipmi-password-from-host-os/index.html b/articles/reset-ipmi-password-from-host-os/index.html index dadfe7fc..492c88d1 100644 --- a/articles/reset-ipmi-password-from-host-os/index.html +++ b/articles/reset-ipmi-password-from-host-os/index.html @@ -4,33 +4,32 @@ - - + + - - - - + + + + - - + - - - - - - - - - - - - - -

            Reset IPMI Credentials from the Host OS

            If you ever find yourself locked out of the Intelligent Platform Management Interface (IPMI) of a server, these + + + + + + + + + + + + + +

            Reset IPMI Credentials from the Host OS

            If you ever find yourself locked out of the Intelligent Platform Management Interface (IPMI) of a server, these instructions will guide your through the process of resetting the credentials to their default values from the host operating system.

            If you are using an operating system like TrueNAS -- good news! It's possible to reset the IPMI password directly from the web interface. This is done by navigating to Network > IPMI, and simply entering a new value in the IPMI @@ -48,5 +47,5 @@ specification, netfn codes ranging from 0x30 to 0x3F are reserved for vendor specific functions. I searched around for some Supermicro references on these vendor specific network functions without much luck other than various support -responses on how to reset a device. Bummer!

            - \ No newline at end of file +responses on how to reset a device. Bummer!

            + \ No newline at end of file diff --git a/articles/ssh-ed25519-sk-yubikey/_payload.json b/articles/ssh-ed25519-sk-yubikey/_payload.json index 77784abf..dd73106a 100644 --- a/articles/ssh-ed25519-sk-yubikey/_payload.json +++ b/articles/ssh-ed25519-sk-yubikey/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":517},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"draft":6,"date":10,"tags":11,"categories":14,"excerpt":17,"body":46,"_type":511,"_id":512,"_source":513,"_file":514,"_stem":515,"_extension":516},"/articles/ssh-ed25519-sk-yubikey","articles",false,"","Configuring a YubiKey for use with OpenSSH","YubiKey's are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" ed25519-sk key type that supports FIDO compliant hardware keys.","2024-06-09",[12,13],"unix","configurations",[15,16],"tooling","tips",{"type":18,"children":19},"root",[20],{"type":21,"tag":22,"props":23,"children":24},"element","p",{},[25,35,37,44],{"type":21,"tag":26,"props":27,"children":31},"a",{"href":28,"rel":29},"https://www.yubico.com/",[30],"nofollow",[32],{"type":33,"value":34},"text","YubiKey's",{"type":33,"value":36}," are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" ",{"type":21,"tag":38,"props":39,"children":41},"code",{"className":40},[],[42],{"type":33,"value":43},"ed25519-sk",{"type":33,"value":45}," key type that supports FIDO compliant hardware keys.",{"type":18,"children":47,"toc":509},[48,63,77,86,100,143,148,192,205,238,243,376,389,484,503],{"type":21,"tag":22,"props":49,"children":50},{},[51,56,57,62],{"type":21,"tag":26,"props":52,"children":54},{"href":28,"rel":53},[30],[55],{"type":33,"value":34},{"type":33,"value":36},{"type":21,"tag":38,"props":58,"children":60},{"className":59},[],[61],{"type":33,"value":43},{"type":33,"value":45},{"type":21,"tag":22,"props":64,"children":65},{},[66,68,75],{"type":33,"value":67},"In ",{"type":21,"tag":26,"props":69,"children":72},{"href":70,"rel":71},"https://www.openssh.com/txt/release-8.2",[30],[73],{"type":33,"value":74},"release 8.2 of OpenSSH",{"type":33,"value":76}," support for FIDO devices was added with public key types \"ecdsa-sk\" and \"ed25519-sk\" (-sk standing for \"security key\"). This key type is supported by YubiKey's with firmware version 5.2.3 or higher.",{"type":21,"tag":78,"props":79,"children":80},"blockquote",{},[81],{"type":21,"tag":22,"props":82,"children":83},{},[84],{"type":33,"value":85},"This release adds support for FIDO/U2F hardware authenticators to OpenSSH. U2F/FIDO are open standards for inexpensive two-factor authentication hardware that are widely used for website authentication. In OpenSSH FIDO devices are supported by new public key types \"ecdsa-sk\" and \"ed25519-sk\", along with corresponding certificate types.",{"type":21,"tag":22,"props":87,"children":88},{},[89,91,98],{"type":33,"value":90},"Let's get started by installing the latest version of OpenSSH via ",{"type":21,"tag":26,"props":92,"children":95},{"href":93,"rel":94},"https://brew.sh/",[30],[96],{"type":33,"value":97},"Homebrew",{"type":33,"value":99},", along with the YubiKey Manager (ykman) CLI. The version of OpenSSH included with macOS is not compatible.",{"type":21,"tag":101,"props":102,"children":106},"pre",{"className":103,"code":104,"language":105,"meta":7,"style":7},"language-sh shiki shiki-themes github-light","$ brew install openssh ykman\n","sh",[107],{"type":21,"tag":38,"props":108,"children":109},{"__ignoreMap":7},[110],{"type":21,"tag":111,"props":112,"children":115},"span",{"class":113,"line":114},"line",1,[116,122,128,133,138],{"type":21,"tag":111,"props":117,"children":119},{"style":118},"--shiki-default:#6F42C1",[120],{"type":33,"value":121},"$",{"type":21,"tag":111,"props":123,"children":125},{"style":124},"--shiki-default:#032F62",[126],{"type":33,"value":127}," brew",{"type":21,"tag":111,"props":129,"children":130},{"style":124},[131],{"type":33,"value":132}," install",{"type":21,"tag":111,"props":134,"children":135},{"style":124},[136],{"type":33,"value":137}," openssh",{"type":21,"tag":111,"props":139,"children":140},{"style":124},[141],{"type":33,"value":142}," ykman\n",{"type":21,"tag":22,"props":144,"children":145},{},[146],{"type":33,"value":147},"Then, let's confirm that our YubiKey has a firmware that is greater than 5.2.3:",{"type":21,"tag":101,"props":149,"children":151},{"className":103,"code":150,"language":105,"meta":7,"style":7},"$ ykman list\nYubiKey 5Ci (5.4.3) [OTP+FIDO+CCID]\n",[152],{"type":21,"tag":38,"props":153,"children":154},{"__ignoreMap":7},[155,172],{"type":21,"tag":111,"props":156,"children":157},{"class":113,"line":114},[158,162,167],{"type":21,"tag":111,"props":159,"children":160},{"style":118},[161],{"type":33,"value":121},{"type":21,"tag":111,"props":163,"children":164},{"style":124},[165],{"type":33,"value":166}," ykman",{"type":21,"tag":111,"props":168,"children":169},{"style":124},[170],{"type":33,"value":171}," list\n",{"type":21,"tag":111,"props":173,"children":175},{"class":113,"line":174},2,[176,181,186],{"type":21,"tag":111,"props":177,"children":178},{"style":118},[179],{"type":33,"value":180},"YubiKey",{"type":21,"tag":111,"props":182,"children":183},{"style":124},[184],{"type":33,"value":185}," 5Ci",{"type":21,"tag":111,"props":187,"children":189},{"style":188},"--shiki-default:#24292E",[190],{"type":33,"value":191}," (5.4.3) [OTP+FIDO+CCID]\n",{"type":21,"tag":22,"props":193,"children":194},{},[195,197,203],{"type":33,"value":196},"Next, we'll go ahead and enable a pin on our device via the ",{"type":21,"tag":38,"props":198,"children":200},{"className":199},[],[201],{"type":33,"value":202},"change-pin",{"type":33,"value":204}," command, as this a requirement for our use.",{"type":21,"tag":101,"props":206,"children":208},{"className":103,"code":207,"language":105,"meta":7,"style":7},"$ ykman fido access change-pin\n",[209],{"type":21,"tag":38,"props":210,"children":211},{"__ignoreMap":7},[212],{"type":21,"tag":111,"props":213,"children":214},{"class":113,"line":114},[215,219,223,228,233],{"type":21,"tag":111,"props":216,"children":217},{"style":118},[218],{"type":33,"value":121},{"type":21,"tag":111,"props":220,"children":221},{"style":124},[222],{"type":33,"value":166},{"type":21,"tag":111,"props":224,"children":225},{"style":124},[226],{"type":33,"value":227}," fido",{"type":21,"tag":111,"props":229,"children":230},{"style":124},[231],{"type":33,"value":232}," access",{"type":21,"tag":111,"props":234,"children":235},{"style":124},[236],{"type":33,"value":237}," change-pin\n",{"type":21,"tag":22,"props":239,"children":240},{},[241],{"type":33,"value":242},"And last, we'll generate the key on our device!",{"type":21,"tag":101,"props":244,"children":246},{"className":103,"code":245,"language":105,"meta":7,"style":7},"$ ssh-keygen -t ed25519-sk -O resident\nGenerating public/private ed25519-sk key pair.\nYou may need to touch your authenticator to authorize key generation.\n...\n",[247],{"type":21,"tag":38,"props":248,"children":249},{"__ignoreMap":7},[250,283,310,367],{"type":21,"tag":111,"props":251,"children":252},{"class":113,"line":114},[253,257,262,268,273,278],{"type":21,"tag":111,"props":254,"children":255},{"style":118},[256],{"type":33,"value":121},{"type":21,"tag":111,"props":258,"children":259},{"style":124},[260],{"type":33,"value":261}," ssh-keygen",{"type":21,"tag":111,"props":263,"children":265},{"style":264},"--shiki-default:#005CC5",[266],{"type":33,"value":267}," -t",{"type":21,"tag":111,"props":269,"children":270},{"style":124},[271],{"type":33,"value":272}," ed25519-sk",{"type":21,"tag":111,"props":274,"children":275},{"style":264},[276],{"type":33,"value":277}," -O",{"type":21,"tag":111,"props":279,"children":280},{"style":124},[281],{"type":33,"value":282}," resident\n",{"type":21,"tag":111,"props":284,"children":285},{"class":113,"line":174},[286,291,296,300,305],{"type":21,"tag":111,"props":287,"children":288},{"style":118},[289],{"type":33,"value":290},"Generating",{"type":21,"tag":111,"props":292,"children":293},{"style":124},[294],{"type":33,"value":295}," public/private",{"type":21,"tag":111,"props":297,"children":298},{"style":124},[299],{"type":33,"value":272},{"type":21,"tag":111,"props":301,"children":302},{"style":124},[303],{"type":33,"value":304}," key",{"type":21,"tag":111,"props":306,"children":307},{"style":124},[308],{"type":33,"value":309}," pair.\n",{"type":21,"tag":111,"props":311,"children":313},{"class":113,"line":312},3,[314,319,324,329,334,339,344,349,353,358,362],{"type":21,"tag":111,"props":315,"children":316},{"style":118},[317],{"type":33,"value":318},"You",{"type":21,"tag":111,"props":320,"children":321},{"style":124},[322],{"type":33,"value":323}," may",{"type":21,"tag":111,"props":325,"children":326},{"style":124},[327],{"type":33,"value":328}," need",{"type":21,"tag":111,"props":330,"children":331},{"style":124},[332],{"type":33,"value":333}," to",{"type":21,"tag":111,"props":335,"children":336},{"style":124},[337],{"type":33,"value":338}," touch",{"type":21,"tag":111,"props":340,"children":341},{"style":124},[342],{"type":33,"value":343}," your",{"type":21,"tag":111,"props":345,"children":346},{"style":124},[347],{"type":33,"value":348}," authenticator",{"type":21,"tag":111,"props":350,"children":351},{"style":124},[352],{"type":33,"value":333},{"type":21,"tag":111,"props":354,"children":355},{"style":124},[356],{"type":33,"value":357}," authorize",{"type":21,"tag":111,"props":359,"children":360},{"style":124},[361],{"type":33,"value":304},{"type":21,"tag":111,"props":363,"children":364},{"style":124},[365],{"type":33,"value":366}," generation.\n",{"type":21,"tag":111,"props":368,"children":370},{"class":113,"line":369},4,[371],{"type":21,"tag":111,"props":372,"children":373},{"style":264},[374],{"type":33,"value":375},"...\n",{"type":21,"tag":22,"props":377,"children":378},{},[379,381,387],{"type":33,"value":380},"We specify ",{"type":21,"tag":382,"props":383,"children":384},"em",{},[385],{"type":33,"value":386},"resident",{"type":33,"value":388}," to indicate that the key handle is to be stored on the YubiKey itself, since we will be using this device with multiple computers.",{"type":21,"tag":101,"props":390,"children":394},{"className":391,"code":392,"language":393,"meta":7,"style":7},"language-txt shiki shiki-themes github-light","resident\n Indicate that the key handle should be stored on the FIDO\n authenticator itself. This makes it easier to use the\n authenticator on multiple computers. Resident keys may be\n supported on FIDO2 authenticators and typically require that a PIN\n be set on the authenticator prior to generation. Resident keys\n may be loaded off the authenticator using ssh-add(1). Storing\n both parts of a key on a FIDO authenticator increases the\n likelihood of an attacker being able to use a stolen authenticator\n device.\n","txt",[395],{"type":21,"tag":38,"props":396,"children":397},{"__ignoreMap":7},[398,406,414,422,430,439,448,457,466,475],{"type":21,"tag":111,"props":399,"children":400},{"class":113,"line":114},[401],{"type":21,"tag":111,"props":402,"children":403},{},[404],{"type":33,"value":405},"resident\n",{"type":21,"tag":111,"props":407,"children":408},{"class":113,"line":174},[409],{"type":21,"tag":111,"props":410,"children":411},{},[412],{"type":33,"value":413}," Indicate that the key handle should be stored on the FIDO\n",{"type":21,"tag":111,"props":415,"children":416},{"class":113,"line":312},[417],{"type":21,"tag":111,"props":418,"children":419},{},[420],{"type":33,"value":421}," authenticator itself. This makes it easier to use the\n",{"type":21,"tag":111,"props":423,"children":424},{"class":113,"line":369},[425],{"type":21,"tag":111,"props":426,"children":427},{},[428],{"type":33,"value":429}," authenticator on multiple computers. Resident keys may be\n",{"type":21,"tag":111,"props":431,"children":433},{"class":113,"line":432},5,[434],{"type":21,"tag":111,"props":435,"children":436},{},[437],{"type":33,"value":438}," supported on FIDO2 authenticators and typically require that a PIN\n",{"type":21,"tag":111,"props":440,"children":442},{"class":113,"line":441},6,[443],{"type":21,"tag":111,"props":444,"children":445},{},[446],{"type":33,"value":447}," be set on the authenticator prior to generation. Resident keys\n",{"type":21,"tag":111,"props":449,"children":451},{"class":113,"line":450},7,[452],{"type":21,"tag":111,"props":453,"children":454},{},[455],{"type":33,"value":456}," may be loaded off the authenticator using ssh-add(1). Storing\n",{"type":21,"tag":111,"props":458,"children":460},{"class":113,"line":459},8,[461],{"type":21,"tag":111,"props":462,"children":463},{},[464],{"type":33,"value":465}," both parts of a key on a FIDO authenticator increases the\n",{"type":21,"tag":111,"props":467,"children":469},{"class":113,"line":468},9,[470],{"type":21,"tag":111,"props":471,"children":472},{},[473],{"type":33,"value":474}," likelihood of an attacker being able to use a stolen authenticator\n",{"type":21,"tag":111,"props":476,"children":478},{"class":113,"line":477},10,[479],{"type":21,"tag":111,"props":480,"children":481},{},[482],{"type":33,"value":483}," device.\n",{"type":21,"tag":22,"props":485,"children":486},{},[487,489,494,496,501],{"type":33,"value":488},"And that's all it takes -- simple enough. Now, when interacting with ",{"type":21,"tag":382,"props":490,"children":491},{},[492],{"type":33,"value":493},"ssh",{"type":33,"value":495}," or ",{"type":21,"tag":382,"props":497,"children":498},{},[499],{"type":33,"value":500},"git",{"type":33,"value":502}," you will be prompted to touch the YubiKey to bring that little bit of physical 2FA.",{"type":21,"tag":504,"props":505,"children":506},"style",{},[507],{"type":33,"value":508},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":174,"depth":174,"links":510},[],"markdown","content:articles:ssh-ed25519-sk-yubikey.md","content","articles/ssh-ed25519-sk-yubikey.md","articles/ssh-ed25519-sk-yubikey","md",1726174739469] \ No newline at end of file +[{"data":1,"prerenderedAt":516},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"draft":6,"date":10,"tags":11,"categories":14,"excerpt":17,"body":46,"_type":511,"_id":512,"_source":513,"_file":514,"_extension":515},"/articles/ssh-ed25519-sk-yubikey","articles",false,"","Configuring a YubiKey for use with OpenSSH","YubiKey's are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" ed25519-sk key type that supports FIDO compliant hardware keys.","2024-06-09",[12,13],"unix","configurations",[15,16],"tooling","tips",{"type":18,"children":19},"root",[20],{"type":21,"tag":22,"props":23,"children":24},"element","p",{},[25,35,37,44],{"type":21,"tag":26,"props":27,"children":31},"a",{"href":28,"rel":29},"https://www.yubico.com/",[30],"nofollow",[32],{"type":33,"value":34},"text","YubiKey's",{"type":33,"value":36}," are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the \"new\" ",{"type":21,"tag":38,"props":39,"children":41},"code",{"className":40},[],[42],{"type":33,"value":43},"ed25519-sk",{"type":33,"value":45}," key type that supports FIDO compliant hardware keys.",{"type":18,"children":47,"toc":509},[48,63,77,86,100,143,148,192,205,238,243,376,389,484,503],{"type":21,"tag":22,"props":49,"children":50},{},[51,56,57,62],{"type":21,"tag":26,"props":52,"children":54},{"href":28,"rel":53},[30],[55],{"type":33,"value":34},{"type":33,"value":36},{"type":21,"tag":38,"props":58,"children":60},{"className":59},[],[61],{"type":33,"value":43},{"type":33,"value":45},{"type":21,"tag":22,"props":64,"children":65},{},[66,68,75],{"type":33,"value":67},"In ",{"type":21,"tag":26,"props":69,"children":72},{"href":70,"rel":71},"https://www.openssh.com/txt/release-8.2",[30],[73],{"type":33,"value":74},"release 8.2 of OpenSSH",{"type":33,"value":76}," support for FIDO devices was added with public key types \"ecdsa-sk\" and \"ed25519-sk\" (-sk standing for \"security key\"). This key type is supported by YubiKey's with firmware version 5.2.3 or higher.",{"type":21,"tag":78,"props":79,"children":80},"blockquote",{},[81],{"type":21,"tag":22,"props":82,"children":83},{},[84],{"type":33,"value":85},"This release adds support for FIDO/U2F hardware authenticators to OpenSSH. U2F/FIDO are open standards for inexpensive two-factor authentication hardware that are widely used for website authentication. In OpenSSH FIDO devices are supported by new public key types \"ecdsa-sk\" and \"ed25519-sk\", along with corresponding certificate types.",{"type":21,"tag":22,"props":87,"children":88},{},[89,91,98],{"type":33,"value":90},"Let's get started by installing the latest version of OpenSSH via ",{"type":21,"tag":26,"props":92,"children":95},{"href":93,"rel":94},"https://brew.sh/",[30],[96],{"type":33,"value":97},"Homebrew",{"type":33,"value":99},", along with the YubiKey Manager (ykman) CLI. The version of OpenSSH included with macOS is not compatible.",{"type":21,"tag":101,"props":102,"children":106},"pre",{"className":103,"code":104,"language":105,"meta":7,"style":7},"language-sh shiki shiki-themes github-light","$ brew install openssh ykman\n","sh",[107],{"type":21,"tag":38,"props":108,"children":109},{"__ignoreMap":7},[110],{"type":21,"tag":111,"props":112,"children":115},"span",{"class":113,"line":114},"line",1,[116,122,128,133,138],{"type":21,"tag":111,"props":117,"children":119},{"style":118},"--shiki-default:#6F42C1",[120],{"type":33,"value":121},"$",{"type":21,"tag":111,"props":123,"children":125},{"style":124},"--shiki-default:#032F62",[126],{"type":33,"value":127}," brew",{"type":21,"tag":111,"props":129,"children":130},{"style":124},[131],{"type":33,"value":132}," install",{"type":21,"tag":111,"props":134,"children":135},{"style":124},[136],{"type":33,"value":137}," openssh",{"type":21,"tag":111,"props":139,"children":140},{"style":124},[141],{"type":33,"value":142}," ykman\n",{"type":21,"tag":22,"props":144,"children":145},{},[146],{"type":33,"value":147},"Then, let's confirm that our YubiKey has a firmware that is greater than 5.2.3:",{"type":21,"tag":101,"props":149,"children":151},{"className":103,"code":150,"language":105,"meta":7,"style":7},"$ ykman list\nYubiKey 5Ci (5.4.3) [OTP+FIDO+CCID]\n",[152],{"type":21,"tag":38,"props":153,"children":154},{"__ignoreMap":7},[155,172],{"type":21,"tag":111,"props":156,"children":157},{"class":113,"line":114},[158,162,167],{"type":21,"tag":111,"props":159,"children":160},{"style":118},[161],{"type":33,"value":121},{"type":21,"tag":111,"props":163,"children":164},{"style":124},[165],{"type":33,"value":166}," ykman",{"type":21,"tag":111,"props":168,"children":169},{"style":124},[170],{"type":33,"value":171}," list\n",{"type":21,"tag":111,"props":173,"children":175},{"class":113,"line":174},2,[176,181,186],{"type":21,"tag":111,"props":177,"children":178},{"style":118},[179],{"type":33,"value":180},"YubiKey",{"type":21,"tag":111,"props":182,"children":183},{"style":124},[184],{"type":33,"value":185}," 5Ci",{"type":21,"tag":111,"props":187,"children":189},{"style":188},"--shiki-default:#24292E",[190],{"type":33,"value":191}," (5.4.3) [OTP+FIDO+CCID]\n",{"type":21,"tag":22,"props":193,"children":194},{},[195,197,203],{"type":33,"value":196},"Next, we'll go ahead and enable a pin on our device via the ",{"type":21,"tag":38,"props":198,"children":200},{"className":199},[],[201],{"type":33,"value":202},"change-pin",{"type":33,"value":204}," command, as this a requirement for our use.",{"type":21,"tag":101,"props":206,"children":208},{"className":103,"code":207,"language":105,"meta":7,"style":7},"$ ykman fido access change-pin\n",[209],{"type":21,"tag":38,"props":210,"children":211},{"__ignoreMap":7},[212],{"type":21,"tag":111,"props":213,"children":214},{"class":113,"line":114},[215,219,223,228,233],{"type":21,"tag":111,"props":216,"children":217},{"style":118},[218],{"type":33,"value":121},{"type":21,"tag":111,"props":220,"children":221},{"style":124},[222],{"type":33,"value":166},{"type":21,"tag":111,"props":224,"children":225},{"style":124},[226],{"type":33,"value":227}," fido",{"type":21,"tag":111,"props":229,"children":230},{"style":124},[231],{"type":33,"value":232}," access",{"type":21,"tag":111,"props":234,"children":235},{"style":124},[236],{"type":33,"value":237}," change-pin\n",{"type":21,"tag":22,"props":239,"children":240},{},[241],{"type":33,"value":242},"And last, we'll generate the key on our device!",{"type":21,"tag":101,"props":244,"children":246},{"className":103,"code":245,"language":105,"meta":7,"style":7},"$ ssh-keygen -t ed25519-sk -O resident\nGenerating public/private ed25519-sk key pair.\nYou may need to touch your authenticator to authorize key generation.\n...\n",[247],{"type":21,"tag":38,"props":248,"children":249},{"__ignoreMap":7},[250,283,310,367],{"type":21,"tag":111,"props":251,"children":252},{"class":113,"line":114},[253,257,262,268,273,278],{"type":21,"tag":111,"props":254,"children":255},{"style":118},[256],{"type":33,"value":121},{"type":21,"tag":111,"props":258,"children":259},{"style":124},[260],{"type":33,"value":261}," ssh-keygen",{"type":21,"tag":111,"props":263,"children":265},{"style":264},"--shiki-default:#005CC5",[266],{"type":33,"value":267}," -t",{"type":21,"tag":111,"props":269,"children":270},{"style":124},[271],{"type":33,"value":272}," ed25519-sk",{"type":21,"tag":111,"props":274,"children":275},{"style":264},[276],{"type":33,"value":277}," -O",{"type":21,"tag":111,"props":279,"children":280},{"style":124},[281],{"type":33,"value":282}," resident\n",{"type":21,"tag":111,"props":284,"children":285},{"class":113,"line":174},[286,291,296,300,305],{"type":21,"tag":111,"props":287,"children":288},{"style":118},[289],{"type":33,"value":290},"Generating",{"type":21,"tag":111,"props":292,"children":293},{"style":124},[294],{"type":33,"value":295}," public/private",{"type":21,"tag":111,"props":297,"children":298},{"style":124},[299],{"type":33,"value":272},{"type":21,"tag":111,"props":301,"children":302},{"style":124},[303],{"type":33,"value":304}," key",{"type":21,"tag":111,"props":306,"children":307},{"style":124},[308],{"type":33,"value":309}," pair.\n",{"type":21,"tag":111,"props":311,"children":313},{"class":113,"line":312},3,[314,319,324,329,334,339,344,349,353,358,362],{"type":21,"tag":111,"props":315,"children":316},{"style":118},[317],{"type":33,"value":318},"You",{"type":21,"tag":111,"props":320,"children":321},{"style":124},[322],{"type":33,"value":323}," may",{"type":21,"tag":111,"props":325,"children":326},{"style":124},[327],{"type":33,"value":328}," need",{"type":21,"tag":111,"props":330,"children":331},{"style":124},[332],{"type":33,"value":333}," to",{"type":21,"tag":111,"props":335,"children":336},{"style":124},[337],{"type":33,"value":338}," touch",{"type":21,"tag":111,"props":340,"children":341},{"style":124},[342],{"type":33,"value":343}," your",{"type":21,"tag":111,"props":345,"children":346},{"style":124},[347],{"type":33,"value":348}," authenticator",{"type":21,"tag":111,"props":350,"children":351},{"style":124},[352],{"type":33,"value":333},{"type":21,"tag":111,"props":354,"children":355},{"style":124},[356],{"type":33,"value":357}," authorize",{"type":21,"tag":111,"props":359,"children":360},{"style":124},[361],{"type":33,"value":304},{"type":21,"tag":111,"props":363,"children":364},{"style":124},[365],{"type":33,"value":366}," generation.\n",{"type":21,"tag":111,"props":368,"children":370},{"class":113,"line":369},4,[371],{"type":21,"tag":111,"props":372,"children":373},{"style":264},[374],{"type":33,"value":375},"...\n",{"type":21,"tag":22,"props":377,"children":378},{},[379,381,387],{"type":33,"value":380},"We specify ",{"type":21,"tag":382,"props":383,"children":384},"em",{},[385],{"type":33,"value":386},"resident",{"type":33,"value":388}," to indicate that the key handle is to be stored on the YubiKey itself, since we will be using this device with multiple computers.",{"type":21,"tag":101,"props":390,"children":394},{"className":391,"code":392,"language":393,"meta":7,"style":7},"language-txt shiki shiki-themes github-light","resident\n Indicate that the key handle should be stored on the FIDO\n authenticator itself. This makes it easier to use the\n authenticator on multiple computers. Resident keys may be\n supported on FIDO2 authenticators and typically require that a PIN\n be set on the authenticator prior to generation. Resident keys\n may be loaded off the authenticator using ssh-add(1). Storing\n both parts of a key on a FIDO authenticator increases the\n likelihood of an attacker being able to use a stolen authenticator\n device.\n","txt",[395],{"type":21,"tag":38,"props":396,"children":397},{"__ignoreMap":7},[398,406,414,422,430,439,448,457,466,475],{"type":21,"tag":111,"props":399,"children":400},{"class":113,"line":114},[401],{"type":21,"tag":111,"props":402,"children":403},{},[404],{"type":33,"value":405},"resident\n",{"type":21,"tag":111,"props":407,"children":408},{"class":113,"line":174},[409],{"type":21,"tag":111,"props":410,"children":411},{},[412],{"type":33,"value":413}," Indicate that the key handle should be stored on the FIDO\n",{"type":21,"tag":111,"props":415,"children":416},{"class":113,"line":312},[417],{"type":21,"tag":111,"props":418,"children":419},{},[420],{"type":33,"value":421}," authenticator itself. This makes it easier to use the\n",{"type":21,"tag":111,"props":423,"children":424},{"class":113,"line":369},[425],{"type":21,"tag":111,"props":426,"children":427},{},[428],{"type":33,"value":429}," authenticator on multiple computers. Resident keys may be\n",{"type":21,"tag":111,"props":431,"children":433},{"class":113,"line":432},5,[434],{"type":21,"tag":111,"props":435,"children":436},{},[437],{"type":33,"value":438}," supported on FIDO2 authenticators and typically require that a PIN\n",{"type":21,"tag":111,"props":440,"children":442},{"class":113,"line":441},6,[443],{"type":21,"tag":111,"props":444,"children":445},{},[446],{"type":33,"value":447}," be set on the authenticator prior to generation. Resident keys\n",{"type":21,"tag":111,"props":449,"children":451},{"class":113,"line":450},7,[452],{"type":21,"tag":111,"props":453,"children":454},{},[455],{"type":33,"value":456}," may be loaded off the authenticator using ssh-add(1). Storing\n",{"type":21,"tag":111,"props":458,"children":460},{"class":113,"line":459},8,[461],{"type":21,"tag":111,"props":462,"children":463},{},[464],{"type":33,"value":465}," both parts of a key on a FIDO authenticator increases the\n",{"type":21,"tag":111,"props":467,"children":469},{"class":113,"line":468},9,[470],{"type":21,"tag":111,"props":471,"children":472},{},[473],{"type":33,"value":474}," likelihood of an attacker being able to use a stolen authenticator\n",{"type":21,"tag":111,"props":476,"children":478},{"class":113,"line":477},10,[479],{"type":21,"tag":111,"props":480,"children":481},{},[482],{"type":33,"value":483}," device.\n",{"type":21,"tag":22,"props":485,"children":486},{},[487,489,494,496,501],{"type":33,"value":488},"And that's all it takes -- simple enough. Now, when interacting with ",{"type":21,"tag":382,"props":490,"children":491},{},[492],{"type":33,"value":493},"ssh",{"type":33,"value":495}," or ",{"type":21,"tag":382,"props":497,"children":498},{},[499],{"type":33,"value":500},"git",{"type":33,"value":502}," you will be prompted to touch the YubiKey to bring that little bit of physical 2FA.",{"type":21,"tag":504,"props":505,"children":506},"style",{},[507],{"type":33,"value":508},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":174,"depth":174,"links":510},[],"markdown","content:articles:ssh-ed25519-sk-yubikey.md","content","articles/ssh-ed25519-sk-yubikey.md","md",1727638398035] \ No newline at end of file diff --git a/articles/ssh-ed25519-sk-yubikey/index.html b/articles/ssh-ed25519-sk-yubikey/index.html index f2f82ca8..72b1484c 100644 --- a/articles/ssh-ed25519-sk-yubikey/index.html +++ b/articles/ssh-ed25519-sk-yubikey/index.html @@ -4,34 +4,33 @@ - - + + - - - - + + + + - - + - - - - - - - - - - - - - - -

            Configuring a YubiKey for use with OpenSSH

            YubiKey's are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the "new" ed25519-sk key type that supports FIDO compliant hardware keys.

            In release 8.2 of OpenSSH support for FIDO devices was added with public key types "ecdsa-sk" and "ed25519-sk" (-sk standing for "security key"). This key type is supported by YubiKey's with firmware version 5.2.3 or higher.

            This release adds support for FIDO/U2F hardware authenticators to OpenSSH. U2F/FIDO are open standards for inexpensive two-factor authentication hardware that are widely used for website authentication. In OpenSSH FIDO devices are supported by new public key types "ecdsa-sk" and "ed25519-sk", along with corresponding certificate types.

            Let's get started by installing the latest version of OpenSSH via Homebrew, along with the YubiKey Manager (ykman) CLI. The version of OpenSSH included with macOS is not compatible.

            $ brew install openssh ykman
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +

            Configuring a YubiKey for use with OpenSSH

            YubiKey's are a convenient way to introduce a physical form of two factor authentication into ones workflow. They support a variety of protocols, but in this guide we will walk through how to configure a YubiKey for use with OpenSSH via the "new" ed25519-sk key type that supports FIDO compliant hardware keys.

            In release 8.2 of OpenSSH support for FIDO devices was added with public key types "ecdsa-sk" and "ed25519-sk" (-sk standing for "security key"). This key type is supported by YubiKey's with firmware version 5.2.3 or higher.

            This release adds support for FIDO/U2F hardware authenticators to OpenSSH. U2F/FIDO are open standards for inexpensive two-factor authentication hardware that are widely used for website authentication. In OpenSSH FIDO devices are supported by new public key types "ecdsa-sk" and "ed25519-sk", along with corresponding certificate types.

            Let's get started by installing the latest version of OpenSSH via Homebrew, along with the YubiKey Manager (ykman) CLI. The version of OpenSSH included with macOS is not compatible.

            $ brew install openssh ykman
             

            Then, let's confirm that our YubiKey has a firmware that is greater than 5.2.3:

            $ ykman list
             YubiKey 5Ci (5.4.3) [OTP+FIDO+CCID]
             

            Next, we'll go ahead and enable a pin on our device via the change-pin command, as this a requirement for our use.

            $ ykman fido access change-pin
            @@ -49,5 +48,5 @@
                     both parts of a key on a FIDO authenticator increases the
                     likelihood of an attacker being able to use a stolen authenticator
                     device.
            -

            And that's all it takes -- simple enough. Now, when interacting with ssh or git you will be prompted to touch the YubiKey to bring that little bit of physical 2FA.

            - \ No newline at end of file +

            And that's all it takes -- simple enough. Now, when interacting with ssh or git you will be prompted to touch the YubiKey to bring that little bit of physical 2FA.

            + \ No newline at end of file diff --git a/articles/unit-testing-micropython-with-mocks/_payload.json b/articles/unit-testing-micropython-with-mocks/_payload.json index 54decc1a..1e3eb526 100644 --- a/articles/unit-testing-micropython-with-mocks/_payload.json +++ b/articles/unit-testing-micropython-with-mocks/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":690},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"draft":6,"tags":11,"categories":16,"excerpt":19,"body":29,"_type":684,"_id":685,"_source":686,"_file":687,"_stem":688,"_extension":689},"/articles/unit-testing-micropython-with-mocks","articles",false,"","Unit Testing in MicroPython with Mocks","Unit testing code for embedded systems can be challenging. While it's possible\nto leverage emulators, write side-effect free code, or run tests on the\nhardware itself, it's often easiest to unit test the code on your personal\ncomputer with mocked hardware functionality.","2020-02-07",[12,13,14,15],"micropython","testing","mocks","tutorial",[17,18],"python","embedded",{"type":20,"children":21},"root",[22],{"type":23,"tag":24,"props":25,"children":26},"element","p",{},[27],{"type":28,"value":9},"text",{"type":20,"children":30,"toc":681},[31,35,42,47,53,75,252,278,398,419,618,646,653,675],{"type":23,"tag":24,"props":32,"children":33},{},[34],{"type":28,"value":9},{"type":23,"tag":36,"props":37,"children":39},"h1",{"id":38},"mocking",[40],{"type":28,"value":41},"Mocking",{"type":23,"tag":24,"props":43,"children":44},{},[45],{"type":28,"value":46},"Mocks allow us to replace the hardware interfacing functionality under-the-hood\nwith predefined results and side-effects. For example, if there is a piece of\nlogic that retrieves values from an accelerometer to get a device's\norientation, it would be possible to mock the returned values of the\naccelerometer -- allowing us to run the unit tests on a device that does not\nhave an accelerometer sensor installed.",{"type":23,"tag":36,"props":48,"children":50},{"id":49},"a-micropython-mocking-example",[51],{"type":28,"value":52},"A MicroPython Mocking Example",{"type":23,"tag":24,"props":54,"children":55},{},[56,58,65,67,73],{"type":28,"value":57},"In this example, we will be unit testing a module named ",{"type":23,"tag":59,"props":60,"children":62},"code",{"className":61},[],[63],{"type":28,"value":64},"time_logger",{"type":28,"value":66},", that\ndepends on the MicroPython library ",{"type":23,"tag":59,"props":68,"children":70},{"className":69},[],[71],{"type":28,"value":72},"utime",{"type":28,"value":74}," to log the most recent Epoch time to\na file.",{"type":23,"tag":76,"props":77,"children":80},"pre",{"className":78,"code":79,"language":17,"meta":7,"style":7},"language-python shiki shiki-themes github-light","# time_logger.py\n\nclass TimeLogger(object):\n\n def save_time(self):\n \"\"\" Overwrite a file with the most recent Epoch timestamp from `utime`\n \"\"\"\n with open(\"LAST_KNOWN_TIME\", \"w+\") as f:\n f.write(str(utime.time()))\n",[81],{"type":23,"tag":59,"props":82,"children":83},{"__ignoreMap":7},[84,96,106,139,147,166,176,185,233],{"type":23,"tag":85,"props":86,"children":89},"span",{"class":87,"line":88},"line",1,[90],{"type":23,"tag":85,"props":91,"children":93},{"style":92},"--shiki-default:#6A737D",[94],{"type":28,"value":95},"# time_logger.py\n",{"type":23,"tag":85,"props":97,"children":99},{"class":87,"line":98},2,[100],{"type":23,"tag":85,"props":101,"children":103},{"emptyLinePlaceholder":102},true,[104],{"type":28,"value":105},"\n",{"type":23,"tag":85,"props":107,"children":109},{"class":87,"line":108},3,[110,116,122,128,134],{"type":23,"tag":85,"props":111,"children":113},{"style":112},"--shiki-default:#D73A49",[114],{"type":28,"value":115},"class",{"type":23,"tag":85,"props":117,"children":119},{"style":118},"--shiki-default:#6F42C1",[120],{"type":28,"value":121}," TimeLogger",{"type":23,"tag":85,"props":123,"children":125},{"style":124},"--shiki-default:#24292E",[126],{"type":28,"value":127},"(",{"type":23,"tag":85,"props":129,"children":131},{"style":130},"--shiki-default:#005CC5",[132],{"type":28,"value":133},"object",{"type":23,"tag":85,"props":135,"children":136},{"style":124},[137],{"type":28,"value":138},"):\n",{"type":23,"tag":85,"props":140,"children":142},{"class":87,"line":141},4,[143],{"type":23,"tag":85,"props":144,"children":145},{"emptyLinePlaceholder":102},[146],{"type":28,"value":105},{"type":23,"tag":85,"props":148,"children":150},{"class":87,"line":149},5,[151,156,161],{"type":23,"tag":85,"props":152,"children":153},{"style":112},[154],{"type":28,"value":155}," def",{"type":23,"tag":85,"props":157,"children":158},{"style":118},[159],{"type":28,"value":160}," save_time",{"type":23,"tag":85,"props":162,"children":163},{"style":124},[164],{"type":28,"value":165},"(self):\n",{"type":23,"tag":85,"props":167,"children":169},{"class":87,"line":168},6,[170],{"type":23,"tag":85,"props":171,"children":173},{"style":172},"--shiki-default:#032F62",[174],{"type":28,"value":175}," \"\"\" Overwrite a file with the most recent Epoch timestamp from `utime`\n",{"type":23,"tag":85,"props":177,"children":179},{"class":87,"line":178},7,[180],{"type":23,"tag":85,"props":181,"children":182},{"style":172},[183],{"type":28,"value":184}," \"\"\"\n",{"type":23,"tag":85,"props":186,"children":188},{"class":87,"line":187},8,[189,194,199,203,208,213,218,223,228],{"type":23,"tag":85,"props":190,"children":191},{"style":112},[192],{"type":28,"value":193}," with",{"type":23,"tag":85,"props":195,"children":196},{"style":130},[197],{"type":28,"value":198}," open",{"type":23,"tag":85,"props":200,"children":201},{"style":124},[202],{"type":28,"value":127},{"type":23,"tag":85,"props":204,"children":205},{"style":172},[206],{"type":28,"value":207},"\"LAST_KNOWN_TIME\"",{"type":23,"tag":85,"props":209,"children":210},{"style":124},[211],{"type":28,"value":212},", ",{"type":23,"tag":85,"props":214,"children":215},{"style":172},[216],{"type":28,"value":217},"\"w+\"",{"type":23,"tag":85,"props":219,"children":220},{"style":124},[221],{"type":28,"value":222},") ",{"type":23,"tag":85,"props":224,"children":225},{"style":112},[226],{"type":28,"value":227},"as",{"type":23,"tag":85,"props":229,"children":230},{"style":124},[231],{"type":28,"value":232}," f:\n",{"type":23,"tag":85,"props":234,"children":236},{"class":87,"line":235},9,[237,242,247],{"type":23,"tag":85,"props":238,"children":239},{"style":124},[240],{"type":28,"value":241}," f.write(",{"type":23,"tag":85,"props":243,"children":244},{"style":130},[245],{"type":28,"value":246},"str",{"type":23,"tag":85,"props":248,"children":249},{"style":124},[250],{"type":28,"value":251},"(utime.time()))\n",{"type":23,"tag":24,"props":253,"children":254},{},[255,257,262,264,269,271,276],{"type":28,"value":256},"First, because the ",{"type":23,"tag":59,"props":258,"children":260},{"className":259},[],[261],{"type":28,"value":72},{"type":28,"value":263}," module is not installed on the machine that the unit\ntests on, we must mock ",{"type":23,"tag":59,"props":265,"children":267},{"className":266},[],[268],{"type":28,"value":72},{"type":28,"value":270}," module before importing ",{"type":23,"tag":59,"props":272,"children":274},{"className":273},[],[275],{"type":28,"value":64},{"type":28,"value":277}," in our\nunit test file.",{"type":23,"tag":76,"props":279,"children":281},{"className":78,"code":280,"language":17,"meta":7,"style":7},"# test_time_logger.py\n\nimport unittest\n\nfrom unittest.mock import MagicMock\n\nsys.modules['utime'] = MagicMock()\nfrom time_logger import TimeLogger\n",[282],{"type":23,"tag":59,"props":283,"children":284},{"__ignoreMap":7},[285,293,300,313,320,342,349,377],{"type":23,"tag":85,"props":286,"children":287},{"class":87,"line":88},[288],{"type":23,"tag":85,"props":289,"children":290},{"style":92},[291],{"type":28,"value":292},"# test_time_logger.py\n",{"type":23,"tag":85,"props":294,"children":295},{"class":87,"line":98},[296],{"type":23,"tag":85,"props":297,"children":298},{"emptyLinePlaceholder":102},[299],{"type":28,"value":105},{"type":23,"tag":85,"props":301,"children":302},{"class":87,"line":108},[303,308],{"type":23,"tag":85,"props":304,"children":305},{"style":112},[306],{"type":28,"value":307},"import",{"type":23,"tag":85,"props":309,"children":310},{"style":124},[311],{"type":28,"value":312}," unittest\n",{"type":23,"tag":85,"props":314,"children":315},{"class":87,"line":141},[316],{"type":23,"tag":85,"props":317,"children":318},{"emptyLinePlaceholder":102},[319],{"type":28,"value":105},{"type":23,"tag":85,"props":321,"children":322},{"class":87,"line":149},[323,328,333,337],{"type":23,"tag":85,"props":324,"children":325},{"style":112},[326],{"type":28,"value":327},"from",{"type":23,"tag":85,"props":329,"children":330},{"style":124},[331],{"type":28,"value":332}," unittest.mock ",{"type":23,"tag":85,"props":334,"children":335},{"style":112},[336],{"type":28,"value":307},{"type":23,"tag":85,"props":338,"children":339},{"style":124},[340],{"type":28,"value":341}," MagicMock\n",{"type":23,"tag":85,"props":343,"children":344},{"class":87,"line":168},[345],{"type":23,"tag":85,"props":346,"children":347},{"emptyLinePlaceholder":102},[348],{"type":28,"value":105},{"type":23,"tag":85,"props":350,"children":351},{"class":87,"line":178},[352,357,362,367,372],{"type":23,"tag":85,"props":353,"children":354},{"style":124},[355],{"type":28,"value":356},"sys.modules[",{"type":23,"tag":85,"props":358,"children":359},{"style":172},[360],{"type":28,"value":361},"'utime'",{"type":23,"tag":85,"props":363,"children":364},{"style":124},[365],{"type":28,"value":366},"] ",{"type":23,"tag":85,"props":368,"children":369},{"style":112},[370],{"type":28,"value":371},"=",{"type":23,"tag":85,"props":373,"children":374},{"style":124},[375],{"type":28,"value":376}," MagicMock()\n",{"type":23,"tag":85,"props":378,"children":379},{"class":87,"line":187},[380,384,389,393],{"type":23,"tag":85,"props":381,"children":382},{"style":112},[383],{"type":28,"value":327},{"type":23,"tag":85,"props":385,"children":386},{"style":124},[387],{"type":28,"value":388}," time_logger ",{"type":23,"tag":85,"props":390,"children":391},{"style":112},[392],{"type":28,"value":307},{"type":23,"tag":85,"props":394,"children":395},{"style":124},[396],{"type":28,"value":397}," TimeLogger\n",{"type":23,"tag":24,"props":399,"children":400},{},[401,403,409,411,417],{"type":28,"value":402},"Then, we can write a test that patches the ",{"type":23,"tag":59,"props":404,"children":406},{"className":405},[],[407],{"type":28,"value":408},"utime.time",{"type":28,"value":410}," functionality so that\nit returns a value of our choosing -- in this case, ",{"type":23,"tag":59,"props":412,"children":414},{"className":413},[],[415],{"type":28,"value":416},"1234",{"type":28,"value":418},".",{"type":23,"tag":76,"props":420,"children":422},{"className":78,"code":421,"language":17,"meta":7,"style":7},"class TestTimeLogger(unittest.TestCase):\n\n def test_save_time(self):\n \"\"\" Verify that the Epoch time is written to file\n \"\"\"\n with unittest.mock.patch(\"utime.time\", return_value=1234):\n t = TimeLogger()\n t.save_time()\n with open(\"LAST_KNOWN_TIME\") as f:\n self.assertEqual(\"1234\", f.read())\n",[423],{"type":23,"tag":59,"props":424,"children":425},{"__ignoreMap":7},[426,460,467,483,491,498,537,554,562,594],{"type":23,"tag":85,"props":427,"children":428},{"class":87,"line":88},[429,433,438,442,447,451,456],{"type":23,"tag":85,"props":430,"children":431},{"style":112},[432],{"type":28,"value":115},{"type":23,"tag":85,"props":434,"children":435},{"style":118},[436],{"type":28,"value":437}," TestTimeLogger",{"type":23,"tag":85,"props":439,"children":440},{"style":124},[441],{"type":28,"value":127},{"type":23,"tag":85,"props":443,"children":444},{"style":118},[445],{"type":28,"value":446},"unittest",{"type":23,"tag":85,"props":448,"children":449},{"style":124},[450],{"type":28,"value":418},{"type":23,"tag":85,"props":452,"children":453},{"style":118},[454],{"type":28,"value":455},"TestCase",{"type":23,"tag":85,"props":457,"children":458},{"style":124},[459],{"type":28,"value":138},{"type":23,"tag":85,"props":461,"children":462},{"class":87,"line":98},[463],{"type":23,"tag":85,"props":464,"children":465},{"emptyLinePlaceholder":102},[466],{"type":28,"value":105},{"type":23,"tag":85,"props":468,"children":469},{"class":87,"line":108},[470,474,479],{"type":23,"tag":85,"props":471,"children":472},{"style":112},[473],{"type":28,"value":155},{"type":23,"tag":85,"props":475,"children":476},{"style":118},[477],{"type":28,"value":478}," test_save_time",{"type":23,"tag":85,"props":480,"children":481},{"style":124},[482],{"type":28,"value":165},{"type":23,"tag":85,"props":484,"children":485},{"class":87,"line":141},[486],{"type":23,"tag":85,"props":487,"children":488},{"style":172},[489],{"type":28,"value":490}," \"\"\" Verify that the Epoch time is written to file\n",{"type":23,"tag":85,"props":492,"children":493},{"class":87,"line":149},[494],{"type":23,"tag":85,"props":495,"children":496},{"style":172},[497],{"type":28,"value":184},{"type":23,"tag":85,"props":499,"children":500},{"class":87,"line":168},[501,505,510,515,519,525,529,533],{"type":23,"tag":85,"props":502,"children":503},{"style":112},[504],{"type":28,"value":193},{"type":23,"tag":85,"props":506,"children":507},{"style":124},[508],{"type":28,"value":509}," unittest.mock.patch(",{"type":23,"tag":85,"props":511,"children":512},{"style":172},[513],{"type":28,"value":514},"\"utime.time\"",{"type":23,"tag":85,"props":516,"children":517},{"style":124},[518],{"type":28,"value":212},{"type":23,"tag":85,"props":520,"children":522},{"style":521},"--shiki-default:#E36209",[523],{"type":28,"value":524},"return_value",{"type":23,"tag":85,"props":526,"children":527},{"style":112},[528],{"type":28,"value":371},{"type":23,"tag":85,"props":530,"children":531},{"style":130},[532],{"type":28,"value":416},{"type":23,"tag":85,"props":534,"children":535},{"style":124},[536],{"type":28,"value":138},{"type":23,"tag":85,"props":538,"children":539},{"class":87,"line":178},[540,545,549],{"type":23,"tag":85,"props":541,"children":542},{"style":124},[543],{"type":28,"value":544}," t ",{"type":23,"tag":85,"props":546,"children":547},{"style":112},[548],{"type":28,"value":371},{"type":23,"tag":85,"props":550,"children":551},{"style":124},[552],{"type":28,"value":553}," TimeLogger()\n",{"type":23,"tag":85,"props":555,"children":556},{"class":87,"line":187},[557],{"type":23,"tag":85,"props":558,"children":559},{"style":124},[560],{"type":28,"value":561}," t.save_time()\n",{"type":23,"tag":85,"props":563,"children":564},{"class":87,"line":235},[565,570,574,578,582,586,590],{"type":23,"tag":85,"props":566,"children":567},{"style":112},[568],{"type":28,"value":569}," with",{"type":23,"tag":85,"props":571,"children":572},{"style":130},[573],{"type":28,"value":198},{"type":23,"tag":85,"props":575,"children":576},{"style":124},[577],{"type":28,"value":127},{"type":23,"tag":85,"props":579,"children":580},{"style":172},[581],{"type":28,"value":207},{"type":23,"tag":85,"props":583,"children":584},{"style":124},[585],{"type":28,"value":222},{"type":23,"tag":85,"props":587,"children":588},{"style":112},[589],{"type":28,"value":227},{"type":23,"tag":85,"props":591,"children":592},{"style":124},[593],{"type":28,"value":232},{"type":23,"tag":85,"props":595,"children":597},{"class":87,"line":596},10,[598,603,608,613],{"type":23,"tag":85,"props":599,"children":600},{"style":130},[601],{"type":28,"value":602}," self",{"type":23,"tag":85,"props":604,"children":605},{"style":124},[606],{"type":28,"value":607},".assertEqual(",{"type":23,"tag":85,"props":609,"children":610},{"style":172},[611],{"type":28,"value":612},"\"1234\"",{"type":23,"tag":85,"props":614,"children":615},{"style":124},[616],{"type":28,"value":617},", f.read())\n",{"type":23,"tag":24,"props":619,"children":620},{},[621,623,629,631,637,639,644],{"type":28,"value":622},"Now, when the ",{"type":23,"tag":59,"props":624,"children":626},{"className":625},[],[627],{"type":28,"value":628},"save_time",{"type":28,"value":630}," method gets the latest time from ",{"type":23,"tag":59,"props":632,"children":634},{"className":633},[],[635],{"type":28,"value":636},"utime.time()",{"type":28,"value":638},", the\nvalue will be patched to return ",{"type":23,"tag":59,"props":640,"children":642},{"className":641},[],[643],{"type":28,"value":416},{"type":28,"value":645},". That value will be written to a file,\nand our unit test will pass!",{"type":23,"tag":647,"props":648,"children":650},"h2",{"id":649},"references",[651],{"type":28,"value":652},"References",{"type":23,"tag":654,"props":655,"children":656},"ol",{},[657],{"type":23,"tag":658,"props":659,"children":660},"li",{},[661],{"type":23,"tag":662,"props":663,"children":667},"a",{"href":664,"rel":665},"https://docs.python.org/3/library/unittest.html",[666],"nofollow",[668,673],{"type":23,"tag":59,"props":669,"children":671},{"className":670},[],[672],{"type":28,"value":446},{"type":28,"value":674}," — Unit testing framework",{"type":23,"tag":676,"props":677,"children":678},"style",{},[679],{"type":28,"value":680},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":98,"depth":98,"links":682},[683],{"id":649,"depth":98,"text":652},"markdown","content:articles:unit-testing-micropython-with-mocks.md","content","articles/unit-testing-micropython-with-mocks.md","articles/unit-testing-micropython-with-mocks","md",1726174739525] \ No newline at end of file +[{"data":1,"prerenderedAt":689},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"draft":6,"tags":11,"categories":16,"excerpt":19,"body":29,"_type":684,"_id":685,"_source":686,"_file":687,"_extension":688},"/articles/unit-testing-micropython-with-mocks","articles",false,"","Unit Testing in MicroPython with Mocks","Unit testing code for embedded systems can be challenging. While it's possible\nto leverage emulators, write side-effect free code, or run tests on the\nhardware itself, it's often easiest to unit test the code on your personal\ncomputer with mocked hardware functionality.","2020-02-07",[12,13,14,15],"micropython","testing","mocks","tutorial",[17,18],"python","embedded",{"type":20,"children":21},"root",[22],{"type":23,"tag":24,"props":25,"children":26},"element","p",{},[27],{"type":28,"value":9},"text",{"type":20,"children":30,"toc":681},[31,35,42,47,53,75,252,278,398,419,618,646,653,675],{"type":23,"tag":24,"props":32,"children":33},{},[34],{"type":28,"value":9},{"type":23,"tag":36,"props":37,"children":39},"h1",{"id":38},"mocking",[40],{"type":28,"value":41},"Mocking",{"type":23,"tag":24,"props":43,"children":44},{},[45],{"type":28,"value":46},"Mocks allow us to replace the hardware interfacing functionality under-the-hood\nwith predefined results and side-effects. For example, if there is a piece of\nlogic that retrieves values from an accelerometer to get a device's\norientation, it would be possible to mock the returned values of the\naccelerometer -- allowing us to run the unit tests on a device that does not\nhave an accelerometer sensor installed.",{"type":23,"tag":36,"props":48,"children":50},{"id":49},"a-micropython-mocking-example",[51],{"type":28,"value":52},"A MicroPython Mocking Example",{"type":23,"tag":24,"props":54,"children":55},{},[56,58,65,67,73],{"type":28,"value":57},"In this example, we will be unit testing a module named ",{"type":23,"tag":59,"props":60,"children":62},"code",{"className":61},[],[63],{"type":28,"value":64},"time_logger",{"type":28,"value":66},", that\ndepends on the MicroPython library ",{"type":23,"tag":59,"props":68,"children":70},{"className":69},[],[71],{"type":28,"value":72},"utime",{"type":28,"value":74}," to log the most recent Epoch time to\na file.",{"type":23,"tag":76,"props":77,"children":80},"pre",{"className":78,"code":79,"language":17,"meta":7,"style":7},"language-python shiki shiki-themes github-light","# time_logger.py\n\nclass TimeLogger(object):\n\n def save_time(self):\n \"\"\" Overwrite a file with the most recent Epoch timestamp from `utime`\n \"\"\"\n with open(\"LAST_KNOWN_TIME\", \"w+\") as f:\n f.write(str(utime.time()))\n",[81],{"type":23,"tag":59,"props":82,"children":83},{"__ignoreMap":7},[84,96,106,139,147,166,176,185,233],{"type":23,"tag":85,"props":86,"children":89},"span",{"class":87,"line":88},"line",1,[90],{"type":23,"tag":85,"props":91,"children":93},{"style":92},"--shiki-default:#6A737D",[94],{"type":28,"value":95},"# time_logger.py\n",{"type":23,"tag":85,"props":97,"children":99},{"class":87,"line":98},2,[100],{"type":23,"tag":85,"props":101,"children":103},{"emptyLinePlaceholder":102},true,[104],{"type":28,"value":105},"\n",{"type":23,"tag":85,"props":107,"children":109},{"class":87,"line":108},3,[110,116,122,128,134],{"type":23,"tag":85,"props":111,"children":113},{"style":112},"--shiki-default:#D73A49",[114],{"type":28,"value":115},"class",{"type":23,"tag":85,"props":117,"children":119},{"style":118},"--shiki-default:#6F42C1",[120],{"type":28,"value":121}," TimeLogger",{"type":23,"tag":85,"props":123,"children":125},{"style":124},"--shiki-default:#24292E",[126],{"type":28,"value":127},"(",{"type":23,"tag":85,"props":129,"children":131},{"style":130},"--shiki-default:#005CC5",[132],{"type":28,"value":133},"object",{"type":23,"tag":85,"props":135,"children":136},{"style":124},[137],{"type":28,"value":138},"):\n",{"type":23,"tag":85,"props":140,"children":142},{"class":87,"line":141},4,[143],{"type":23,"tag":85,"props":144,"children":145},{"emptyLinePlaceholder":102},[146],{"type":28,"value":105},{"type":23,"tag":85,"props":148,"children":150},{"class":87,"line":149},5,[151,156,161],{"type":23,"tag":85,"props":152,"children":153},{"style":112},[154],{"type":28,"value":155}," def",{"type":23,"tag":85,"props":157,"children":158},{"style":118},[159],{"type":28,"value":160}," save_time",{"type":23,"tag":85,"props":162,"children":163},{"style":124},[164],{"type":28,"value":165},"(self):\n",{"type":23,"tag":85,"props":167,"children":169},{"class":87,"line":168},6,[170],{"type":23,"tag":85,"props":171,"children":173},{"style":172},"--shiki-default:#032F62",[174],{"type":28,"value":175}," \"\"\" Overwrite a file with the most recent Epoch timestamp from `utime`\n",{"type":23,"tag":85,"props":177,"children":179},{"class":87,"line":178},7,[180],{"type":23,"tag":85,"props":181,"children":182},{"style":172},[183],{"type":28,"value":184}," \"\"\"\n",{"type":23,"tag":85,"props":186,"children":188},{"class":87,"line":187},8,[189,194,199,203,208,213,218,223,228],{"type":23,"tag":85,"props":190,"children":191},{"style":112},[192],{"type":28,"value":193}," with",{"type":23,"tag":85,"props":195,"children":196},{"style":130},[197],{"type":28,"value":198}," open",{"type":23,"tag":85,"props":200,"children":201},{"style":124},[202],{"type":28,"value":127},{"type":23,"tag":85,"props":204,"children":205},{"style":172},[206],{"type":28,"value":207},"\"LAST_KNOWN_TIME\"",{"type":23,"tag":85,"props":209,"children":210},{"style":124},[211],{"type":28,"value":212},", ",{"type":23,"tag":85,"props":214,"children":215},{"style":172},[216],{"type":28,"value":217},"\"w+\"",{"type":23,"tag":85,"props":219,"children":220},{"style":124},[221],{"type":28,"value":222},") ",{"type":23,"tag":85,"props":224,"children":225},{"style":112},[226],{"type":28,"value":227},"as",{"type":23,"tag":85,"props":229,"children":230},{"style":124},[231],{"type":28,"value":232}," f:\n",{"type":23,"tag":85,"props":234,"children":236},{"class":87,"line":235},9,[237,242,247],{"type":23,"tag":85,"props":238,"children":239},{"style":124},[240],{"type":28,"value":241}," f.write(",{"type":23,"tag":85,"props":243,"children":244},{"style":130},[245],{"type":28,"value":246},"str",{"type":23,"tag":85,"props":248,"children":249},{"style":124},[250],{"type":28,"value":251},"(utime.time()))\n",{"type":23,"tag":24,"props":253,"children":254},{},[255,257,262,264,269,271,276],{"type":28,"value":256},"First, because the ",{"type":23,"tag":59,"props":258,"children":260},{"className":259},[],[261],{"type":28,"value":72},{"type":28,"value":263}," module is not installed on the machine that the unit\ntests on, we must mock ",{"type":23,"tag":59,"props":265,"children":267},{"className":266},[],[268],{"type":28,"value":72},{"type":28,"value":270}," module before importing ",{"type":23,"tag":59,"props":272,"children":274},{"className":273},[],[275],{"type":28,"value":64},{"type":28,"value":277}," in our\nunit test file.",{"type":23,"tag":76,"props":279,"children":281},{"className":78,"code":280,"language":17,"meta":7,"style":7},"# test_time_logger.py\n\nimport unittest\n\nfrom unittest.mock import MagicMock\n\nsys.modules['utime'] = MagicMock()\nfrom time_logger import TimeLogger\n",[282],{"type":23,"tag":59,"props":283,"children":284},{"__ignoreMap":7},[285,293,300,313,320,342,349,377],{"type":23,"tag":85,"props":286,"children":287},{"class":87,"line":88},[288],{"type":23,"tag":85,"props":289,"children":290},{"style":92},[291],{"type":28,"value":292},"# test_time_logger.py\n",{"type":23,"tag":85,"props":294,"children":295},{"class":87,"line":98},[296],{"type":23,"tag":85,"props":297,"children":298},{"emptyLinePlaceholder":102},[299],{"type":28,"value":105},{"type":23,"tag":85,"props":301,"children":302},{"class":87,"line":108},[303,308],{"type":23,"tag":85,"props":304,"children":305},{"style":112},[306],{"type":28,"value":307},"import",{"type":23,"tag":85,"props":309,"children":310},{"style":124},[311],{"type":28,"value":312}," unittest\n",{"type":23,"tag":85,"props":314,"children":315},{"class":87,"line":141},[316],{"type":23,"tag":85,"props":317,"children":318},{"emptyLinePlaceholder":102},[319],{"type":28,"value":105},{"type":23,"tag":85,"props":321,"children":322},{"class":87,"line":149},[323,328,333,337],{"type":23,"tag":85,"props":324,"children":325},{"style":112},[326],{"type":28,"value":327},"from",{"type":23,"tag":85,"props":329,"children":330},{"style":124},[331],{"type":28,"value":332}," unittest.mock ",{"type":23,"tag":85,"props":334,"children":335},{"style":112},[336],{"type":28,"value":307},{"type":23,"tag":85,"props":338,"children":339},{"style":124},[340],{"type":28,"value":341}," MagicMock\n",{"type":23,"tag":85,"props":343,"children":344},{"class":87,"line":168},[345],{"type":23,"tag":85,"props":346,"children":347},{"emptyLinePlaceholder":102},[348],{"type":28,"value":105},{"type":23,"tag":85,"props":350,"children":351},{"class":87,"line":178},[352,357,362,367,372],{"type":23,"tag":85,"props":353,"children":354},{"style":124},[355],{"type":28,"value":356},"sys.modules[",{"type":23,"tag":85,"props":358,"children":359},{"style":172},[360],{"type":28,"value":361},"'utime'",{"type":23,"tag":85,"props":363,"children":364},{"style":124},[365],{"type":28,"value":366},"] ",{"type":23,"tag":85,"props":368,"children":369},{"style":112},[370],{"type":28,"value":371},"=",{"type":23,"tag":85,"props":373,"children":374},{"style":124},[375],{"type":28,"value":376}," MagicMock()\n",{"type":23,"tag":85,"props":378,"children":379},{"class":87,"line":187},[380,384,389,393],{"type":23,"tag":85,"props":381,"children":382},{"style":112},[383],{"type":28,"value":327},{"type":23,"tag":85,"props":385,"children":386},{"style":124},[387],{"type":28,"value":388}," time_logger ",{"type":23,"tag":85,"props":390,"children":391},{"style":112},[392],{"type":28,"value":307},{"type":23,"tag":85,"props":394,"children":395},{"style":124},[396],{"type":28,"value":397}," TimeLogger\n",{"type":23,"tag":24,"props":399,"children":400},{},[401,403,409,411,417],{"type":28,"value":402},"Then, we can write a test that patches the ",{"type":23,"tag":59,"props":404,"children":406},{"className":405},[],[407],{"type":28,"value":408},"utime.time",{"type":28,"value":410}," functionality so that\nit returns a value of our choosing -- in this case, ",{"type":23,"tag":59,"props":412,"children":414},{"className":413},[],[415],{"type":28,"value":416},"1234",{"type":28,"value":418},".",{"type":23,"tag":76,"props":420,"children":422},{"className":78,"code":421,"language":17,"meta":7,"style":7},"class TestTimeLogger(unittest.TestCase):\n\n def test_save_time(self):\n \"\"\" Verify that the Epoch time is written to file\n \"\"\"\n with unittest.mock.patch(\"utime.time\", return_value=1234):\n t = TimeLogger()\n t.save_time()\n with open(\"LAST_KNOWN_TIME\") as f:\n self.assertEqual(\"1234\", f.read())\n",[423],{"type":23,"tag":59,"props":424,"children":425},{"__ignoreMap":7},[426,460,467,483,491,498,537,554,562,594],{"type":23,"tag":85,"props":427,"children":428},{"class":87,"line":88},[429,433,438,442,447,451,456],{"type":23,"tag":85,"props":430,"children":431},{"style":112},[432],{"type":28,"value":115},{"type":23,"tag":85,"props":434,"children":435},{"style":118},[436],{"type":28,"value":437}," TestTimeLogger",{"type":23,"tag":85,"props":439,"children":440},{"style":124},[441],{"type":28,"value":127},{"type":23,"tag":85,"props":443,"children":444},{"style":118},[445],{"type":28,"value":446},"unittest",{"type":23,"tag":85,"props":448,"children":449},{"style":124},[450],{"type":28,"value":418},{"type":23,"tag":85,"props":452,"children":453},{"style":118},[454],{"type":28,"value":455},"TestCase",{"type":23,"tag":85,"props":457,"children":458},{"style":124},[459],{"type":28,"value":138},{"type":23,"tag":85,"props":461,"children":462},{"class":87,"line":98},[463],{"type":23,"tag":85,"props":464,"children":465},{"emptyLinePlaceholder":102},[466],{"type":28,"value":105},{"type":23,"tag":85,"props":468,"children":469},{"class":87,"line":108},[470,474,479],{"type":23,"tag":85,"props":471,"children":472},{"style":112},[473],{"type":28,"value":155},{"type":23,"tag":85,"props":475,"children":476},{"style":118},[477],{"type":28,"value":478}," test_save_time",{"type":23,"tag":85,"props":480,"children":481},{"style":124},[482],{"type":28,"value":165},{"type":23,"tag":85,"props":484,"children":485},{"class":87,"line":141},[486],{"type":23,"tag":85,"props":487,"children":488},{"style":172},[489],{"type":28,"value":490}," \"\"\" Verify that the Epoch time is written to file\n",{"type":23,"tag":85,"props":492,"children":493},{"class":87,"line":149},[494],{"type":23,"tag":85,"props":495,"children":496},{"style":172},[497],{"type":28,"value":184},{"type":23,"tag":85,"props":499,"children":500},{"class":87,"line":168},[501,505,510,515,519,525,529,533],{"type":23,"tag":85,"props":502,"children":503},{"style":112},[504],{"type":28,"value":193},{"type":23,"tag":85,"props":506,"children":507},{"style":124},[508],{"type":28,"value":509}," unittest.mock.patch(",{"type":23,"tag":85,"props":511,"children":512},{"style":172},[513],{"type":28,"value":514},"\"utime.time\"",{"type":23,"tag":85,"props":516,"children":517},{"style":124},[518],{"type":28,"value":212},{"type":23,"tag":85,"props":520,"children":522},{"style":521},"--shiki-default:#E36209",[523],{"type":28,"value":524},"return_value",{"type":23,"tag":85,"props":526,"children":527},{"style":112},[528],{"type":28,"value":371},{"type":23,"tag":85,"props":530,"children":531},{"style":130},[532],{"type":28,"value":416},{"type":23,"tag":85,"props":534,"children":535},{"style":124},[536],{"type":28,"value":138},{"type":23,"tag":85,"props":538,"children":539},{"class":87,"line":178},[540,545,549],{"type":23,"tag":85,"props":541,"children":542},{"style":124},[543],{"type":28,"value":544}," t ",{"type":23,"tag":85,"props":546,"children":547},{"style":112},[548],{"type":28,"value":371},{"type":23,"tag":85,"props":550,"children":551},{"style":124},[552],{"type":28,"value":553}," TimeLogger()\n",{"type":23,"tag":85,"props":555,"children":556},{"class":87,"line":187},[557],{"type":23,"tag":85,"props":558,"children":559},{"style":124},[560],{"type":28,"value":561}," t.save_time()\n",{"type":23,"tag":85,"props":563,"children":564},{"class":87,"line":235},[565,570,574,578,582,586,590],{"type":23,"tag":85,"props":566,"children":567},{"style":112},[568],{"type":28,"value":569}," with",{"type":23,"tag":85,"props":571,"children":572},{"style":130},[573],{"type":28,"value":198},{"type":23,"tag":85,"props":575,"children":576},{"style":124},[577],{"type":28,"value":127},{"type":23,"tag":85,"props":579,"children":580},{"style":172},[581],{"type":28,"value":207},{"type":23,"tag":85,"props":583,"children":584},{"style":124},[585],{"type":28,"value":222},{"type":23,"tag":85,"props":587,"children":588},{"style":112},[589],{"type":28,"value":227},{"type":23,"tag":85,"props":591,"children":592},{"style":124},[593],{"type":28,"value":232},{"type":23,"tag":85,"props":595,"children":597},{"class":87,"line":596},10,[598,603,608,613],{"type":23,"tag":85,"props":599,"children":600},{"style":130},[601],{"type":28,"value":602}," self",{"type":23,"tag":85,"props":604,"children":605},{"style":124},[606],{"type":28,"value":607},".assertEqual(",{"type":23,"tag":85,"props":609,"children":610},{"style":172},[611],{"type":28,"value":612},"\"1234\"",{"type":23,"tag":85,"props":614,"children":615},{"style":124},[616],{"type":28,"value":617},", f.read())\n",{"type":23,"tag":24,"props":619,"children":620},{},[621,623,629,631,637,639,644],{"type":28,"value":622},"Now, when the ",{"type":23,"tag":59,"props":624,"children":626},{"className":625},[],[627],{"type":28,"value":628},"save_time",{"type":28,"value":630}," method gets the latest time from ",{"type":23,"tag":59,"props":632,"children":634},{"className":633},[],[635],{"type":28,"value":636},"utime.time()",{"type":28,"value":638},", the\nvalue will be patched to return ",{"type":23,"tag":59,"props":640,"children":642},{"className":641},[],[643],{"type":28,"value":416},{"type":28,"value":645},". That value will be written to a file,\nand our unit test will pass!",{"type":23,"tag":647,"props":648,"children":650},"h2",{"id":649},"references",[651],{"type":28,"value":652},"References",{"type":23,"tag":654,"props":655,"children":656},"ol",{},[657],{"type":23,"tag":658,"props":659,"children":660},"li",{},[661],{"type":23,"tag":662,"props":663,"children":667},"a",{"href":664,"rel":665},"https://docs.python.org/3/library/unittest.html",[666],"nofollow",[668,673],{"type":23,"tag":59,"props":669,"children":671},{"className":670},[],[672],{"type":28,"value":446},{"type":28,"value":674}," — Unit testing framework",{"type":23,"tag":676,"props":677,"children":678},"style",{},[679],{"type":28,"value":680},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":98,"depth":98,"links":682},[683],{"id":649,"depth":98,"text":652},"markdown","content:articles:unit-testing-micropython-with-mocks.md","content","articles/unit-testing-micropython-with-mocks.md","md",1727638398053] \ No newline at end of file diff --git a/articles/unit-testing-micropython-with-mocks/index.html b/articles/unit-testing-micropython-with-mocks/index.html index 32ff8708..aaec5792 100644 --- a/articles/unit-testing-micropython-with-mocks/index.html +++ b/articles/unit-testing-micropython-with-mocks/index.html @@ -4,36 +4,35 @@ - - + + - - - - + + + + - - + - - - - - - - - - - - - - - - - -

            Unit Testing in MicroPython with Mocks

            Unit testing code for embedded systems can be challenging. While it's possible + + + + + + + + + + + + + + + + +

            Unit Testing in MicroPython with Mocks

            Unit testing code for embedded systems can be challenging. While it's possible to leverage emulators, write side-effect free code, or run tests on the hardware itself, it's often easiest to unit test the code on your personal computer with mocked hardware functionality.

            Mocking

            Mocks allow us to replace the hardware interfacing functionality under-the-hood @@ -75,5 +74,5 @@ self.assertEqual("1234", f.read())

            Now, when the save_time method gets the latest time from utime.time(), the value will be patched to return 1234. That value will be written to a file, -and our unit test will pass!

            References

            1. unittest — Unit testing framework
            - \ No newline at end of file +and our unit test will pass!

            References

            1. unittest — Unit testing framework
            + \ No newline at end of file diff --git a/articles/vim-fugitive-gpg-pinentry/_payload.json b/articles/vim-fugitive-gpg-pinentry/_payload.json index 6fb0601c..cf7a09a6 100644 --- a/articles/vim-fugitive-gpg-pinentry/_payload.json +++ b/articles/vim-fugitive-gpg-pinentry/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":329},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"draft":6,"date":10,"tags":11,"categories":14,"excerpt":17,"body":56,"_type":323,"_id":324,"_source":325,"_file":326,"_stem":327,"_extension":328},"/articles/vim-fugitive-gpg-pinentry","articles",false,"","Using pinentry-mac to sign commits from vim-fugitive","In order to sign git commits from within Vim using a plugin like tpope/vim-fugitive, it is necessary to configure the gpg-agent to use a GUI based pinentry-program.","2024-05-11",[12,13],"vim","tip",[15,16],"tooling","tips",{"type":18,"children":19},"root",[20],{"type":21,"tag":22,"props":23,"children":24},"element","p",{},[25,28,37,39,46,48,54],{"type":26,"value":27},"text","In order to sign git commits from within Vim using a plugin like ",{"type":21,"tag":29,"props":30,"children":34},"a",{"href":31,"rel":32},"https://github.com/tpope/vim-fugitive",[33],"nofollow",[35],{"type":26,"value":36},"tpope/vim-fugitive",{"type":26,"value":38},", it is necessary to configure the ",{"type":21,"tag":40,"props":41,"children":43},"code",{"className":42},[],[44],{"type":26,"value":45},"gpg-agent",{"type":26,"value":47}," to use a GUI based ",{"type":21,"tag":40,"props":49,"children":51},{"className":50},[],[52],{"type":26,"value":53},"pinentry-program",{"type":26,"value":55},".",{"type":18,"children":57,"toc":319},[58,80,87,129,135,140,178,198,206,218,250,255,308,313],{"type":21,"tag":22,"props":59,"children":60},{},[61,62,67,68,73,74,79],{"type":26,"value":27},{"type":21,"tag":29,"props":63,"children":65},{"href":31,"rel":64},[33],[66],{"type":26,"value":36},{"type":26,"value":38},{"type":21,"tag":40,"props":69,"children":71},{"className":70},[],[72],{"type":26,"value":45},{"type":26,"value":47},{"type":21,"tag":40,"props":75,"children":77},{"className":76},[],[78],{"type":26,"value":53},{"type":26,"value":55},{"type":21,"tag":81,"props":82,"children":84},"h2",{"id":83},"preface",[85],{"type":26,"value":86},"Preface",{"type":21,"tag":22,"props":88,"children":89},{},[90,92,99,101,106,107,112,114,120,122,128],{"type":26,"value":91},"The man, the myth, the legend, Timothy Popallopollis himself ",{"type":21,"tag":29,"props":93,"children":96},{"href":94,"rel":95},"https://github.com/tpope/vim-fugitive/issues/846#issuecomment-253816577",[33],[97],{"type":26,"value":98},"recommends",{"type":26,"value":100}," configuring your ",{"type":21,"tag":40,"props":102,"children":104},{"className":103},[],[105],{"type":26,"value":45},{"type":26,"value":47},{"type":21,"tag":40,"props":108,"children":110},{"className":109},[],[111],{"type":26,"value":53},{"type":26,"value":113},". On macOS this can be done quite by simply installing ",{"type":21,"tag":40,"props":115,"children":117},{"className":116},[],[118],{"type":26,"value":119},"pinentry-mac",{"type":26,"value":121},", and updating your ",{"type":21,"tag":40,"props":123,"children":125},{"className":124},[],[126],{"type":26,"value":127},"gpg-agent.conf",{"type":26,"value":55},{"type":21,"tag":81,"props":130,"children":132},{"id":131},"configuration",[133],{"type":26,"value":134},"Configuration",{"type":21,"tag":22,"props":136,"children":137},{},[138],{"type":26,"value":139},"First things first, let's install the pinentry program.",{"type":21,"tag":141,"props":142,"children":146},"pre",{"code":143,"language":144,"meta":7,"className":145,"style":7},"$ brew install pinentry-mac\n","bash","language-bash shiki shiki-themes github-light",[147],{"type":21,"tag":40,"props":148,"children":149},{"__ignoreMap":7},[150],{"type":21,"tag":151,"props":152,"children":155},"span",{"class":153,"line":154},"line",1,[156,162,168,173],{"type":21,"tag":151,"props":157,"children":159},{"style":158},"--shiki-default:#6F42C1",[160],{"type":26,"value":161},"$",{"type":21,"tag":151,"props":163,"children":165},{"style":164},"--shiki-default:#032F62",[166],{"type":26,"value":167}," brew",{"type":21,"tag":151,"props":169,"children":170},{"style":164},[171],{"type":26,"value":172}," install",{"type":21,"tag":151,"props":174,"children":175},{"style":164},[176],{"type":26,"value":177}," pinentry-mac\n",{"type":21,"tag":22,"props":179,"children":180},{},[181,183,188,190,196],{"type":26,"value":182},"Then, all we need to do is set the ",{"type":21,"tag":40,"props":184,"children":186},{"className":185},[],[187],{"type":26,"value":53},{"type":26,"value":189}," option in your ",{"type":21,"tag":40,"props":191,"children":193},{"className":192},[],[194],{"type":26,"value":195},"~/.gnupg/gpg-agent.conf",{"type":26,"value":197}," file.",{"type":21,"tag":141,"props":199,"children":201},{"code":200},"default-cache-ttl 600\nmax-cache-ttl 7200\npinentry-program /opt/homebrew/bin/pinentry-mac\n",[202],{"type":21,"tag":40,"props":203,"children":204},{"__ignoreMap":7},[205],{"type":26,"value":200},{"type":21,"tag":22,"props":207,"children":208},{},[209,211,217],{"type":26,"value":210},"If your don't know the path to your pinentry program, you can throw down a quick ",{"type":21,"tag":40,"props":212,"children":214},{"className":213},[],[215],{"type":26,"value":216},"which",{"type":26,"value":55},{"type":21,"tag":141,"props":219,"children":221},{"code":220,"language":144,"meta":7,"className":145,"style":7},"$ which pinentry-mac\n/opt/homebrew/bin/pinentry-mac\n",[222],{"type":21,"tag":40,"props":223,"children":224},{"__ignoreMap":7},[225,241],{"type":21,"tag":151,"props":226,"children":227},{"class":153,"line":154},[228,232,237],{"type":21,"tag":151,"props":229,"children":230},{"style":158},[231],{"type":26,"value":161},{"type":21,"tag":151,"props":233,"children":234},{"style":164},[235],{"type":26,"value":236}," which",{"type":21,"tag":151,"props":238,"children":239},{"style":164},[240],{"type":26,"value":177},{"type":21,"tag":151,"props":242,"children":244},{"class":153,"line":243},2,[245],{"type":21,"tag":151,"props":246,"children":247},{"style":158},[248],{"type":26,"value":249},"/opt/homebrew/bin/pinentry-mac\n",{"type":21,"tag":22,"props":251,"children":252},{},[253],{"type":26,"value":254},"Or use your Homebrew prefix.",{"type":21,"tag":141,"props":256,"children":258},{"code":257,"language":144,"meta":7,"className":145,"style":7},"$ echo $(brew --prefix)/bin/pinentry-mac\n/opt/homebrew/bin/pinentry-mac\n",[259],{"type":21,"tag":40,"props":260,"children":261},{"__ignoreMap":7},[262,301],{"type":21,"tag":151,"props":263,"children":264},{"class":153,"line":154},[265,269,274,280,285,291,296],{"type":21,"tag":151,"props":266,"children":267},{"style":158},[268],{"type":26,"value":161},{"type":21,"tag":151,"props":270,"children":271},{"style":164},[272],{"type":26,"value":273}," echo",{"type":21,"tag":151,"props":275,"children":277},{"style":276},"--shiki-default:#24292E",[278],{"type":26,"value":279}," $(",{"type":21,"tag":151,"props":281,"children":282},{"style":158},[283],{"type":26,"value":284},"brew",{"type":21,"tag":151,"props":286,"children":288},{"style":287},"--shiki-default:#005CC5",[289],{"type":26,"value":290}," --prefix",{"type":21,"tag":151,"props":292,"children":293},{"style":276},[294],{"type":26,"value":295},")",{"type":21,"tag":151,"props":297,"children":298},{"style":164},[299],{"type":26,"value":300},"/bin/pinentry-mac\n",{"type":21,"tag":151,"props":302,"children":303},{"class":153,"line":243},[304],{"type":21,"tag":151,"props":305,"children":306},{"style":158},[307],{"type":26,"value":249},{"type":21,"tag":22,"props":309,"children":310},{},[311],{"type":26,"value":312},"But that's all it takes. Now, you should be prompted to enter your gpg pin in an external window when signing commits from vim.",{"type":21,"tag":314,"props":315,"children":316},"style",{},[317],{"type":26,"value":318},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":243,"depth":243,"links":320},[321,322],{"id":83,"depth":243,"text":86},{"id":131,"depth":243,"text":134},"markdown","content:articles:vim-fugitive-gpg-pinentry.md","content","articles/vim-fugitive-gpg-pinentry.md","articles/vim-fugitive-gpg-pinentry","md",1726174739471] \ No newline at end of file +[{"data":1,"prerenderedAt":322},["Reactive",2],{"page-data":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"draft":6,"date":10,"tags":11,"categories":14,"excerpt":17,"body":56,"_type":317,"_id":318,"_source":319,"_file":320,"_extension":321},"/articles/vim-fugitive-gpg-pinentry","articles",false,"","Using pinentry-mac to sign commits from vim-fugitive","In order to sign git commits from within Vim using a plugin like tpope/vim-fugitive, it is necessary to configure the gpg-agent to use a GUI based pinentry-program.","2024-05-11",[12,13],"vim","tip",[15,16],"tooling","tips",{"type":18,"children":19},"root",[20],{"type":21,"tag":22,"props":23,"children":24},"element","p",{},[25,28,37,39,46,48,54],{"type":26,"value":27},"text","In order to sign git commits from within Vim using a plugin like ",{"type":21,"tag":29,"props":30,"children":34},"a",{"href":31,"rel":32},"https://github.com/tpope/vim-fugitive",[33],"nofollow",[35],{"type":26,"value":36},"tpope/vim-fugitive",{"type":26,"value":38},", it is necessary to configure the ",{"type":21,"tag":40,"props":41,"children":43},"code",{"className":42},[],[44],{"type":26,"value":45},"gpg-agent",{"type":26,"value":47}," to use a GUI based ",{"type":21,"tag":40,"props":49,"children":51},{"className":50},[],[52],{"type":26,"value":53},"pinentry-program",{"type":26,"value":55},".",{"type":18,"children":57,"toc":313},[58,80,87,129,135,140,178,198,206,218,250,255,302,307],{"type":21,"tag":22,"props":59,"children":60},{},[61,62,67,68,73,74,79],{"type":26,"value":27},{"type":21,"tag":29,"props":63,"children":65},{"href":31,"rel":64},[33],[66],{"type":26,"value":36},{"type":26,"value":38},{"type":21,"tag":40,"props":69,"children":71},{"className":70},[],[72],{"type":26,"value":45},{"type":26,"value":47},{"type":21,"tag":40,"props":75,"children":77},{"className":76},[],[78],{"type":26,"value":53},{"type":26,"value":55},{"type":21,"tag":81,"props":82,"children":84},"h2",{"id":83},"preface",[85],{"type":26,"value":86},"Preface",{"type":21,"tag":22,"props":88,"children":89},{},[90,92,99,101,106,107,112,114,120,122,128],{"type":26,"value":91},"The man, the myth, the legend, Timothy Popallopollis himself ",{"type":21,"tag":29,"props":93,"children":96},{"href":94,"rel":95},"https://github.com/tpope/vim-fugitive/issues/846#issuecomment-253816577",[33],[97],{"type":26,"value":98},"recommends",{"type":26,"value":100}," configuring your ",{"type":21,"tag":40,"props":102,"children":104},{"className":103},[],[105],{"type":26,"value":45},{"type":26,"value":47},{"type":21,"tag":40,"props":108,"children":110},{"className":109},[],[111],{"type":26,"value":53},{"type":26,"value":113},". On macOS this can be done quite by simply installing ",{"type":21,"tag":40,"props":115,"children":117},{"className":116},[],[118],{"type":26,"value":119},"pinentry-mac",{"type":26,"value":121},", and updating your ",{"type":21,"tag":40,"props":123,"children":125},{"className":124},[],[126],{"type":26,"value":127},"gpg-agent.conf",{"type":26,"value":55},{"type":21,"tag":81,"props":130,"children":132},{"id":131},"configuration",[133],{"type":26,"value":134},"Configuration",{"type":21,"tag":22,"props":136,"children":137},{},[138],{"type":26,"value":139},"First things first, let's install the pinentry program.",{"type":21,"tag":141,"props":142,"children":146},"pre",{"code":143,"language":144,"meta":7,"className":145,"style":7},"$ brew install pinentry-mac\n","bash","language-bash shiki shiki-themes github-light",[147],{"type":21,"tag":40,"props":148,"children":149},{"__ignoreMap":7},[150],{"type":21,"tag":151,"props":152,"children":155},"span",{"class":153,"line":154},"line",1,[156,162,168,173],{"type":21,"tag":151,"props":157,"children":159},{"style":158},"--shiki-default:#6F42C1",[160],{"type":26,"value":161},"$",{"type":21,"tag":151,"props":163,"children":165},{"style":164},"--shiki-default:#032F62",[166],{"type":26,"value":167}," brew",{"type":21,"tag":151,"props":169,"children":170},{"style":164},[171],{"type":26,"value":172}," install",{"type":21,"tag":151,"props":174,"children":175},{"style":164},[176],{"type":26,"value":177}," pinentry-mac\n",{"type":21,"tag":22,"props":179,"children":180},{},[181,183,188,190,196],{"type":26,"value":182},"Then, all we need to do is set the ",{"type":21,"tag":40,"props":184,"children":186},{"className":185},[],[187],{"type":26,"value":53},{"type":26,"value":189}," option in your ",{"type":21,"tag":40,"props":191,"children":193},{"className":192},[],[194],{"type":26,"value":195},"~/.gnupg/gpg-agent.conf",{"type":26,"value":197}," file.",{"type":21,"tag":141,"props":199,"children":201},{"code":200},"default-cache-ttl 600\nmax-cache-ttl 7200\npinentry-program /opt/homebrew/bin/pinentry-mac\n",[202],{"type":21,"tag":40,"props":203,"children":204},{"__ignoreMap":7},[205],{"type":26,"value":200},{"type":21,"tag":22,"props":207,"children":208},{},[209,211,217],{"type":26,"value":210},"If your don't know the path to your pinentry program, you can throw down a quick ",{"type":21,"tag":40,"props":212,"children":214},{"className":213},[],[215],{"type":26,"value":216},"which",{"type":26,"value":55},{"type":21,"tag":141,"props":219,"children":221},{"code":220,"language":144,"meta":7,"className":145,"style":7},"$ which pinentry-mac\n/opt/homebrew/bin/pinentry-mac\n",[222],{"type":21,"tag":40,"props":223,"children":224},{"__ignoreMap":7},[225,241],{"type":21,"tag":151,"props":226,"children":227},{"class":153,"line":154},[228,232,237],{"type":21,"tag":151,"props":229,"children":230},{"style":158},[231],{"type":26,"value":161},{"type":21,"tag":151,"props":233,"children":234},{"style":164},[235],{"type":26,"value":236}," which",{"type":21,"tag":151,"props":238,"children":239},{"style":164},[240],{"type":26,"value":177},{"type":21,"tag":151,"props":242,"children":244},{"class":153,"line":243},2,[245],{"type":21,"tag":151,"props":246,"children":247},{"style":158},[248],{"type":26,"value":249},"/opt/homebrew/bin/pinentry-mac\n",{"type":21,"tag":22,"props":251,"children":252},{},[253],{"type":26,"value":254},"Or use your Homebrew prefix.",{"type":21,"tag":141,"props":256,"children":258},{"code":257,"language":144,"meta":7,"className":145,"style":7},"$ echo $(brew --prefix)/bin/pinentry-mac\n/opt/homebrew/bin/pinentry-mac\n",[259],{"type":21,"tag":40,"props":260,"children":261},{"__ignoreMap":7},[262,295],{"type":21,"tag":151,"props":263,"children":264},{"class":153,"line":154},[265,269,274,279,284,290],{"type":21,"tag":151,"props":266,"children":267},{"style":158},[268],{"type":26,"value":161},{"type":21,"tag":151,"props":270,"children":271},{"style":164},[272],{"type":26,"value":273}," echo",{"type":21,"tag":151,"props":275,"children":276},{"style":164},[277],{"type":26,"value":278}," $(",{"type":21,"tag":151,"props":280,"children":281},{"style":158},[282],{"type":26,"value":283},"brew",{"type":21,"tag":151,"props":285,"children":287},{"style":286},"--shiki-default:#005CC5",[288],{"type":26,"value":289}," --prefix",{"type":21,"tag":151,"props":291,"children":292},{"style":164},[293],{"type":26,"value":294},")/bin/pinentry-mac\n",{"type":21,"tag":151,"props":296,"children":297},{"class":153,"line":243},[298],{"type":21,"tag":151,"props":299,"children":300},{"style":158},[301],{"type":26,"value":249},{"type":21,"tag":22,"props":303,"children":304},{},[305],{"type":26,"value":306},"But that's all it takes. Now, you should be prompted to enter your gpg pin in an external window when signing commits from vim.",{"type":21,"tag":308,"props":309,"children":310},"style",{},[311],{"type":26,"value":312},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":243,"depth":243,"links":314},[315,316],{"id":83,"depth":243,"text":86},{"id":131,"depth":243,"text":134},"markdown","content:articles:vim-fugitive-gpg-pinentry.md","content","articles/vim-fugitive-gpg-pinentry.md","md",1727638398037] \ No newline at end of file diff --git a/articles/vim-fugitive-gpg-pinentry/index.html b/articles/vim-fugitive-gpg-pinentry/index.html index c06b35a3..644af8e7 100644 --- a/articles/vim-fugitive-gpg-pinentry/index.html +++ b/articles/vim-fugitive-gpg-pinentry/index.html @@ -4,39 +4,38 @@ - - + + - - - - + + + + - - + - - - - - - - - - - - - - -
            Category
            Tags

            Using pinentry-mac to sign commits from vim-fugitive

            In order to sign git commits from within Vim using a plugin like tpope/vim-fugitive, it is necessary to configure the gpg-agent to use a GUI based pinentry-program.

            Preface

            The man, the myth, the legend, Timothy Popallopollis himself recommends configuring your gpg-agent to use a GUI based pinentry-program. On macOS this can be done quite by simply installing pinentry-mac, and updating your gpg-agent.conf.

            Configuration

            First things first, let's install the pinentry program.

            $ brew install pinentry-mac
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            Category
            Tags

            Using pinentry-mac to sign commits from vim-fugitive

            In order to sign git commits from within Vim using a plugin like tpope/vim-fugitive, it is necessary to configure the gpg-agent to use a GUI based pinentry-program.

            Preface

            The man, the myth, the legend, Timothy Popallopollis himself recommends configuring your gpg-agent to use a GUI based pinentry-program. On macOS this can be done quite by simply installing pinentry-mac, and updating your gpg-agent.conf.

            Configuration

            First things first, let's install the pinentry program.

            $ brew install pinentry-mac
             

            Then, all we need to do is set the pinentry-program option in your ~/.gnupg/gpg-agent.conf file.

            default-cache-ttl 600
             max-cache-ttl 7200
             pinentry-program /opt/homebrew/bin/pinentry-mac
             

            If your don't know the path to your pinentry program, you can throw down a quick which.

            $ which pinentry-mac
             /opt/homebrew/bin/pinentry-mac
            -

            Or use your Homebrew prefix.

            $ echo $(brew --prefix)/bin/pinentry-mac
            +

            Or use your Homebrew prefix.

            $ echo $(brew --prefix)/bin/pinentry-mac
             /opt/homebrew/bin/pinentry-mac
            -

            But that's all it takes. Now, you should be prompted to enter your gpg pin in an external window when signing commits from vim.

            - \ No newline at end of file +

            But that's all it takes. Now, you should be prompted to enter your gpg pin in an external window when signing commits from vim.

            + \ No newline at end of file diff --git a/atom/index.html b/atom/index.html index 1368c22a..d35d9029 100644 --- a/atom/index.html +++ b/atom/index.html @@ -2,7 +2,7 @@ https://cmpadden.github.io cmpadden.github.io - 2024-09-12T20:58:59.101Z + 2024-09-29T19:33:17.562Z Nuxt static site generation + Feed for Node.js Colton Padden diff --git a/card/_payload.json b/card/_payload.json index 96d0eb68..3c8ea93e 100644 --- a/card/_payload.json +++ b/card/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["Reactive",2],{},1726174738537] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["Reactive",2],{},1727638396944] \ No newline at end of file diff --git a/card/index.html b/card/index.html index 2ddeb563..8fb5e617 100644 --- a/card/index.html +++ b/card/index.html @@ -4,12 +4,12 @@ - - - - - - - -
            TL;DR
            Name
            Colton
            Profession
            Astronaut
            Hobby
            Skydiving
            - \ No newline at end of file + + + + + + + +
            TL;DR
            Name
            Colton
            Profession
            Astronaut
            Hobby
            Skydiving
            + \ No newline at end of file diff --git a/examples/nested_transitions/_payload.json b/examples/nested_transitions/_payload.json index 2a0686c5..bba52d93 100644 --- a/examples/nested_transitions/_payload.json +++ b/examples/nested_transitions/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["Reactive",2],{},1726174738538] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["Reactive",2],{},1727638396945] \ No newline at end of file diff --git a/examples/nested_transitions/index.html b/examples/nested_transitions/index.html index 45133682..c98113e4 100644 --- a/examples/nested_transitions/index.html +++ b/examples/nested_transitions/index.html @@ -4,12 +4,12 @@ - - - - - - - -
            - \ No newline at end of file + + + + + + + +
            + \ No newline at end of file diff --git a/index.html b/index.html index 8b930025..489ca104 100644 --- a/index.html +++ b/index.html @@ -4,16 +4,16 @@ - - - - - - - + + + + + + + - - - -
            I help educate data engineers while building the future of data orchestration at Dagster.
            Previously, I worked at Gemini building the data platform that provided company-wide insights into the exchange and business. At Georgetown University's Massive Data Institute building data warehousing, processing solutions, and portals to aid social scientists and researchers to leverage large-scale organic data. And previously I provided consulting for financial institutions and government agencies in the D.C. area around data practices, and identity and access management.
            - \ No newline at end of file + + + +
            I help educate data engineers while building the future of data orchestration at Dagster.
            Previously, I worked at Gemini building the data platform that provided company-wide insights into the exchange and business. At Georgetown University's Massive Data Institute building data warehousing, processing solutions, and portals to aid social scientists and researchers to leverage large-scale organic data. And previously I provided consulting for financial institutions and government agencies in the D.C. area around data practices, and identity and access management.
            + \ No newline at end of file diff --git a/playground/_payload.json b/playground/_payload.json index 4329cf1e..3d7c6567 100644 --- a/playground/_payload.json +++ b/playground/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["Reactive",2],{},1726174738542] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["Reactive",2],{},1727638396952] \ No newline at end of file diff --git a/playground/audio/_payload.json b/playground/audio/_payload.json index d7825733..4b991e88 100644 --- a/playground/audio/_payload.json +++ b/playground/audio/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["Reactive",2],{},1726174738540] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["Reactive",2],{},1727638396947] \ No newline at end of file diff --git a/playground/audio/index.html b/playground/audio/index.html index 8b3cd229..6bb6128f 100644 --- a/playground/audio/index.html +++ b/playground/audio/index.html @@ -4,12 +4,12 @@ - - - - - - - -
            Enable
            Disable
            Time Domain Waveform
            Frequency Spectrogram
            Frequency Bar Chart
            Frequency Buffer History
            IndexMeanMinMaxFFTBuffer
            Time Domain Buffer History
            IndexMeanMinMaxFFTBuffer
            - \ No newline at end of file + + + + + + + +
            Enable
            Disable
            Time Domain Waveform
            Frequency Spectrogram
            Frequency Bar Chart
            Frequency Buffer History
            IndexMeanMinMaxFFTBuffer
            Time Domain Buffer History
            IndexMeanMinMaxFFTBuffer
            + \ No newline at end of file diff --git a/playground/chords/_payload.json b/playground/chords/_payload.json index d7825733..863ad8a7 100644 --- a/playground/chords/_payload.json +++ b/playground/chords/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["Reactive",2],{},1726174738540] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["Reactive",2],{},1727638396948] \ No newline at end of file diff --git a/playground/chords/index.html b/playground/chords/index.html index b2e7f43c..b2c2554a 100644 --- a/playground/chords/index.html +++ b/playground/chords/index.html @@ -4,12 +4,12 @@ - - - - - - - -
            Unfortunately, the Web MIDI API is not supported in all browsers...
            - \ No newline at end of file + + + + + + + +
            Unfortunately, the Web MIDI API is not supported in all browsers...
            + \ No newline at end of file diff --git a/playground/conway/_payload.json b/playground/conway/_payload.json index 25e181c8..389e9288 100644 --- a/playground/conway/_payload.json +++ b/playground/conway/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["Reactive",2],{},1726174738541] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["Reactive",2],{},1727638396950] \ No newline at end of file diff --git a/playground/conway/index.html b/playground/conway/index.html index a9ccb033..8577798b 100644 --- a/playground/conway/index.html +++ b/playground/conway/index.html @@ -4,12 +4,12 @@ - - - - - - - -
            - \ No newline at end of file + + + + + + + +
            + \ No newline at end of file diff --git a/playground/french/_payload.json b/playground/french/_payload.json index 4329cf1e..1e1c3de9 100644 --- a/playground/french/_payload.json +++ b/playground/french/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["Reactive",2],{},1726174738542] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["Reactive",2],{},1727638396951] \ No newline at end of file diff --git a/playground/french/index.html b/playground/french/index.html index a0f8f0a3..db115e15 100644 --- a/playground/french/index.html +++ b/playground/french/index.html @@ -4,14 +4,14 @@ - - - - - + + + + + - - - -
            1000 French Conjugations
            Loading...
            - \ No newline at end of file + + + +
            1000 French Conjugations
            Loading...
            + \ No newline at end of file diff --git a/playground/index.html b/playground/index.html index 6f7abcbe..3dfd0a10 100644 --- a/playground/index.html +++ b/playground/index.html @@ -4,13 +4,13 @@ - - - - - - - - -
            - \ No newline at end of file + + + + + + + + +
            + \ No newline at end of file diff --git a/playground/matrix/_payload.json b/playground/matrix/_payload.json index 2a975089..565c2710 100644 --- a/playground/matrix/_payload.json +++ b/playground/matrix/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["Reactive",2],{},1726174738543] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["Reactive",2],{},1727638396954] \ No newline at end of file diff --git a/playground/matrix/index.html b/playground/matrix/index.html index 9eecfaba..75a2b478 100644 --- a/playground/matrix/index.html +++ b/playground/matrix/index.html @@ -4,12 +4,12 @@ - - - - - - - -
            Walk through the steps of matrix multiplication with randomly generated matrices. Press the Spacebar or click the buttons to iterate through the steps.
            Matrix A
            Matrix B
            - \ No newline at end of file + + + + + + + +
            Walk through the steps of matrix multiplication with randomly generated matrices. Press the Spacebar or click the buttons to iterate through the steps.
            Matrix A
            Matrix B
            + \ No newline at end of file diff --git a/playground/metronome/_payload.json b/playground/metronome/_payload.json index 193067d8..a2bd0244 100644 --- a/playground/metronome/_payload.json +++ b/playground/metronome/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["Reactive",2],{},1726174738544] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["Reactive",2],{},1727638396955] \ No newline at end of file diff --git a/playground/metronome/index.html b/playground/metronome/index.html index 383300f6..6d5a16a2 100644 --- a/playground/metronome/index.html +++ b/playground/metronome/index.html @@ -4,12 +4,12 @@ - - - - - - - -
            - \ No newline at end of file + + + + + + + +
            + \ No newline at end of file diff --git a/playground/midi/_payload.json b/playground/midi/_payload.json index 208e5da6..a2bd0244 100644 --- a/playground/midi/_payload.json +++ b/playground/midi/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["Reactive",2],{},1726174738545] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["Reactive",2],{},1727638396955] \ No newline at end of file diff --git a/playground/midi/index.html b/playground/midi/index.html index d940e695..a98d2d3d 100644 --- a/playground/midi/index.html +++ b/playground/midi/index.html @@ -4,12 +4,12 @@ - - - - - - - -
            Unfortunately, the Web MIDI API is not supported in all browsers...
            - \ No newline at end of file + + + + + + + +
            Unfortunately, the Web MIDI API is not supported in all browsers...
            + \ No newline at end of file diff --git a/playground/palettes/mountains/_payload.json b/playground/palettes/mountains/_payload.json index 208e5da6..ae319bcd 100644 --- a/playground/palettes/mountains/_payload.json +++ b/playground/palettes/mountains/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["Reactive",2],{},1726174738545] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["Reactive",2],{},1727638396956] \ No newline at end of file diff --git a/playground/palettes/mountains/index.html b/playground/palettes/mountains/index.html index 97336c4e..0f9d60a8 100644 --- a/playground/palettes/mountains/index.html +++ b/playground/palettes/mountains/index.html @@ -4,12 +4,12 @@ - - - - - - - -
            Click or tap anywhere to redraw the waves!
            - \ No newline at end of file + + + + + + + +
            Click or tap anywhere to redraw the waves!
            + \ No newline at end of file diff --git a/playground/palettes/variance/_payload.json b/playground/palettes/variance/_payload.json index 5023c676..2b79df12 100644 --- a/playground/palettes/variance/_payload.json +++ b/playground/palettes/variance/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["Reactive",2],{},1726174738546] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["Reactive",2],{},1727638396957] \ No newline at end of file diff --git a/playground/palettes/variance/index.html b/playground/palettes/variance/index.html index 41b29120..8d57017e 100644 --- a/playground/palettes/variance/index.html +++ b/playground/palettes/variance/index.html @@ -4,12 +4,12 @@ - - - - - - - -
            - \ No newline at end of file + + + + + + + +
            + \ No newline at end of file diff --git a/playground/plotter/_payload.json b/playground/plotter/_payload.json index 4cd943a2..ba0f22cc 100644 --- a/playground/plotter/_payload.json +++ b/playground/plotter/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["Reactive",2],{},1726174738547] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["Reactive",2],{},1727638396959] \ No newline at end of file diff --git a/playground/plotter/index.html b/playground/plotter/index.html index aa199b41..319fddb2 100644 --- a/playground/plotter/index.html +++ b/playground/plotter/index.html @@ -4,12 +4,12 @@ - - - - - - - -
            - \ No newline at end of file + + + + + + + +
            + \ No newline at end of file diff --git a/playground/tiling/_payload.json b/playground/tiling/_payload.json index 641e058f..cb04c609 100644 --- a/playground/tiling/_payload.json +++ b/playground/tiling/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["Reactive",2],{},1726174738548] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["Reactive",2],{},1727638396960] \ No newline at end of file diff --git a/playground/tiling/index.html b/playground/tiling/index.html index 87b12a57..06eebd8e 100644 --- a/playground/tiling/index.html +++ b/playground/tiling/index.html @@ -4,12 +4,12 @@ - - - - - - - -
            m-ary tree based tiling
            - \ No newline at end of file + + + + + + + +
            m-ary tree based tiling
            + \ No newline at end of file diff --git a/playground/waves/_payload.json b/playground/waves/_payload.json index 4e846645..73de1160 100644 --- a/playground/waves/_payload.json +++ b/playground/waves/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["Reactive",2],{},1726174739053] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["Reactive",2],{},1727638397461] \ No newline at end of file diff --git a/playground/waves/index.html b/playground/waves/index.html index c8de5f89..4ca8eca7 100644 --- a/playground/waves/index.html +++ b/playground/waves/index.html @@ -4,12 +4,12 @@ - - - - - - - -
            y(x) = A sin((2π / λ) x)
            y(x) = A cos((2π / λ) x)
            y(x) = A tan((2π / λ) x)
            Click or tap anywhere to clear the canvas!
            - \ No newline at end of file + + + + + + + +
            y(x) = A sin((2π / λ) x)
            y(x) = A cos((2π / λ) x)
            y(x) = A tan((2π / λ) x)
            Click or tap anywhere to clear the canvas!
            + \ No newline at end of file diff --git a/talks/_payload.json b/talks/_payload.json index f6460658..cf02e1c9 100644 --- a/talks/_payload.json +++ b/talks/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["Reactive",2],{},1726174739054] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["Reactive",2],{},1727638397465] \ No newline at end of file diff --git a/talks/index.html b/talks/index.html index 8287f629..a555732a 100644 --- a/talks/index.html +++ b/talks/index.html @@ -4,12 +4,12 @@ - - - - - - - -

            Talks

            Sep 06, 2024
            Dagster Deep Dive
            Data Quality: Building Reliable Data Platforms
            May 18, 2024
            MotherDuck and Dagster
            From local development to production
            Apr 05, 2024
            Dagster Deep Dive
            Configurations and Resources
            - \ No newline at end of file + + + + + + + +

            Talks

            Sep 24, 2024
            Dagster Deep Dive
            Orchestrating ML Workloads with Dagster & Modal
            Aug 06, 2024
            Dagster Deep Dive
            Data Quality: Building Reliable Data Platforms
            Apr 18, 2024
            MotherDuck and Dagster
            From local development to production
            Mar 05, 2024
            Dagster Deep Dive
            Configurations and Resources
            + \ No newline at end of file