From 416890e1bed793cbe9b40deff52ce4806196f1b5 Mon Sep 17 00:00:00 2001 From: Huakun Shen Date: Sun, 12 Jan 2025 22:02:24 -0500 Subject: [PATCH] init with kunkun worker template --- .gitignore | 177 +++++++++++++++++++++++++++++++++++++++ .npmrc | 1 + README.md | 125 +++++++++++++++++++++++++++ build.ts | 30 +++++++ bun.lockb | Bin 0 -> 98361 bytes ossinsight-logo copy.svg | 1 + ossinsight-logo.svg | 1 + package.json | 56 +++++++++++++ src/i18n/en.ts | 5 ++ src/i18n/index.ts | 20 +++++ src/i18n/zh.ts | 5 ++ src/index.ts | 80 ++++++++++++++++++ tsconfig.json | 27 ++++++ 13 files changed, 528 insertions(+) create mode 100644 .gitignore create mode 100644 .npmrc create mode 100644 README.md create mode 100644 build.ts create mode 100755 bun.lockb create mode 100644 ossinsight-logo copy.svg create mode 100644 ossinsight-logo.svg create mode 100644 package.json create mode 100644 src/i18n/en.ts create mode 100644 src/i18n/index.ts create mode 100644 src/i18n/zh.ts create mode 100644 src/index.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8c67a06 --- /dev/null +++ b/.gitignore @@ -0,0 +1,177 @@ +# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore + +# Logs + +logs +_.log +npm-debug.log_ +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Caches + +.cache + +# Diagnostic reports (https://nodejs.org/api/report.html) + +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# Runtime data + +pids +_.pid +_.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover + +lib-cov + +# Coverage directory used by tools like istanbul + +coverage +*.lcov + +# nyc test coverage + +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) + +.grunt + +# Bower dependency directory (https://bower.io/) + +bower_components + +# node-waf configuration + +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) + +build/Release + +# Dependency directories + +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) + +web_modules/ + +# TypeScript cache + +*.tsbuildinfo + +# Optional npm cache directory + +.npm + +# Optional eslint cache + +.eslintcache + +# Optional stylelint cache + +.stylelintcache + +# Microbundle cache + +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history + +.node_repl_history + +# Output of 'npm pack' + +*.tgz + +# Yarn Integrity file + +.yarn-integrity + +# dotenv environment variable files + +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) + +.parcel-cache + +# Next.js build output + +.next +out + +# Nuxt.js build / generate output + +.nuxt +dist + +# Gatsby files + +# Comment in the public line in if your project uses Gatsby and not Next.js + +# https://nextjs.org/blog/next-9-1#public-directory-support + +# public + +# vuepress build output + +.vuepress/dist + +# vuepress v2.x temp and cache directory + +.temp + +# Docusaurus cache and generated files + +.docusaurus + +# Serverless directories + +.serverless/ + +# FuseBox cache + +.fusebox/ + +# DynamoDB Local files + +.dynamodb/ + +# TernJS port file + +.tern-port + +# Stores VSCode versions used for testing VSCode extensions + +.vscode-test + +# yarn v2 + +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# IntelliJ based IDEs +.idea + +# Finder (MacOS) folder config +.DS_Store +extensions_support/ + diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..41583e3 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +@jsr:registry=https://npm.jsr.io diff --git a/README.md b/README.md new file mode 100644 index 0000000..e1c7cc7 --- /dev/null +++ b/README.md @@ -0,0 +1,125 @@ +# Kunkun Template UI Extension + +This is a template for a template UI extension. (UI follows pre-defined template) + +[./src/index.ts](./src/index.ts) is the default entrypoint for the extension. You can import any other files in this file, but the build process will bundle them into a single file. + +## Pros and Cons + +This type of extension is suitable for simple use cases, such as a list or form. All components are pre-defined, so there is not much room for customization. If you want more flexibility on the UI, consider using [Custom UI Extension](https://docs.kunkun.sh/extensions/custom-ui-ext/), which requires some frontend knowledge but gives you full control over the UI. + +Read documentation at https://docs.kunkun.sh/extensions/worker-template/ + +Make sure you understand what this type of extension is capable of. + +### Pros + +- Simple to develop, no need for any frontend knowledge. +- Small bundle size (~40KB) + - [Custom UI Extension](https://docs.kunkun.sh/extensions/custom-ui-ext/) are usually larger than 300KB. + +### Cons + +- Limited UI customization. Not suitable for complex use cases. + +Consider [Custom UI Extension](https://docs.kunkun.sh/extensions/custom-ui-ext/) if you need more complex UI. + +## Development + +```bash +pnpm install +``` + +Start extension in development mode. Every save will trigger a hot reload in Kunkun. + +```bash +pnpm dev +``` + +- During development, right click in Kunkun to open the developer tools. + - Error messages will be shown in the console. + - If you got any permission error while calling Kunknu's APIs, make sure you've declared the permission in `package.json`. Then go back to home page and enter the extension again to re-apply the permission. +- To develop and preview the extension in Kunkun, you need to run the `Add Dev Extension` command in Kunkun, and register this extension's path. + +Build the extension. Your extension source code can contain many files, but the build process will bundle them into a single file. + +```bash +pnpm build +# Due to Bun's bug, if you are on windows, and install dependencies with pnpm, you may get error during build. +# Try install dependencies with bun or npm instead. +``` + +## i18n + +[./src/i18n](./src/i18n/) contains optional internationalization support starter code. + +If you want to support i18n, you can use the `t` function to translate the strings in the extension. + +User's language setting is available via `app.language()`. + +```ts +import { app } from "@kksh/api/ui/worker" +import { setupI18n, t } from "./src/i18n" + +setupI18n("zh") +console.log(t("welcome")) + +setupI18n(await app.language()) +console.log(t("welcome")) +``` + +## Add More Commands + +If you want to add more template worker extension commands, simply modify the `entrypoints` array in [./build.ts](./build.ts). + +Then in `package.json`, register the new command. + +## Verify Build and Publish + +```bash +pnpm build # make sure the build npm script works +npx kksh@latest verify # Verify some basic settings +npx kksh@latest verify --publish # Verify some basic settings before publishing +``` + +It is recommended to build the extension with the same environment our CI uses. + +The docker image used by our CI is `huakunshen/kunkun-ext-builder:latest`. + +You can use the following command to build the extension with the same environment our CI uses. +This requires you to have docker installed, and the shell you are using has access to it via `docker` command. + +```bash +npx kksh@latest build # Build the extension with +``` + +`pnpm` is used to install dependencies and build the extension. + +The docker image environment also has `node`, `pnpm`, `npm`, `bun`, `deno` installed. +If your build failed, try debug with `huakunshen/kunkun-ext-builder:latest` image in interative mode and bind your extension volume to `/workspace`. + +After build successfully, you should find a tarball file ends with `.tgz` in the root of your extension. +The tarball is packaged with `npm pack` command. You can uncompress it to see if it contains all the necessary files. + +This tarball is the final product that will be published and installed in Kunkun. You can further verify your extension by installing this tarball directly in Kunkun. + +After verifying the tarball, it's ready to be published. + +Fork [KunkunExtensions](https://github.com/kunkunsh/KunkunExtensions) repo, add your extension to the `extensions` directory, and create a PR. + +Once CI passed and PR merged, you can use your extension in Kunkun. + +## Potential Error + +Our CI uses `pnpm` to install dependencies. If you are on Windows, you may get error during build. + +See issue https://github.com/kunkunsh/kunkun/issues/78 + +`bun` had problem building the extension when `pnpm` is used to install dependencies. + +### Options + +1. Install an older version of `bun` (1.1.27 should work) +2. Install dependencies with `bun` or `npm` instead of `pnpm` + +Our CI always builds the extension with on Linux and shouldn't have this problem. diff --git a/build.ts b/build.ts new file mode 100644 index 0000000..a99deb5 --- /dev/null +++ b/build.ts @@ -0,0 +1,30 @@ +import { watch } from "fs" +import { join } from "path" +import { refreshTemplateWorkerExtension } from "@kksh/api/dev" +import { $ } from "bun" + +const entrypoints = ["./src/index.ts"] + +async function build() { + try { + for (const entrypoint of entrypoints) { + await $`bun build --minify --target=browser --outdir=./dist ${entrypoint}` + } + if (Bun.argv.includes("dev")) { + await refreshTemplateWorkerExtension() + } + } catch (error) { + console.error(error) + } +} + +const srcDir = join(import.meta.dir, "src") + +await build() + +if (Bun.argv.includes("dev")) { + console.log(`Watching ${srcDir} for changes...`) + watch(srcDir, { recursive: true }, async (event, filename) => { + await build() + }) +} diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..3714cedcfb1e7434ae540456430015100b62ab6d GIT binary patch literal 98361 zcmeFacRZKh|3Ch;S28MFW@Ybenc1uCME2f$C4^*E8i<67P*O>R5Sc|}B%6j&L@EmX z&dKw7zpwY}_IdSs>izxw_kP?u?$2|sbH6_xXI|&JJiT6A9KwPAe!_OHUc!!ELF{&c zUgRJNdU)HrJGpu|3OafFdD;dD28od4V=x%!WG=r*d%3Bi>*M(63vJa-MiOzy6cNQx z*-|HepCj5?bOI05!eH<=0YmyLhxr#qVe`i~upfQ_69yCIDk|;e7!rWV10~x*{v*I0 z0Br%10SvPBaJBOez}OLBFf1T{8F-*VmFs|VdXN_f$N-QNAPqpEjUfkEL$s+ANxYeF z0tj_|078GBp&qvWpsurrx1C)m22(?V!BBwm`v74*H_#NQQw9*`?fh)*9RXn<$iQ+> zfKaCnAiVDB=;!PxhQS;I^`VZdzaW&x6obmJz5ytw1}F?J!gihlxDDV-fUsSP*y~QV z{sF!qEqv%-v!2xZI``^x4Wx@t)G*>W00d) zfIk-q4#syI{DA%9=VM$qd{1SDnWo9@tMEted*^ zSUkLYv!4n9!Z>|w16%~%9Ycd%TaZu_w%s_80-&z0Gk2J7lasf6(DFr zln=mN01p9#<0l6Y_8T`q*shOYeZlL!03mM|7$@k@KgiJ|05~Y-+Kej)AnXq@fS}1y zsQ_WzG1ziFfRN|t4+ajz;pp!v2sRpwy@!7Yj4J?KhwXO*2>a^@K*+bX_x1zR2g3^T zFb=hSn{nI%2;&pPq8ZQTb$>_CAV)tC6TzmA4)5kXR|W`mmjQw)6*Yw|7X}EXW|W7w z!>@&d^j8;XKU@b70m6QY!{+e;a)Nv%=nuI66k+!tWg!fP9ppIy!hR$K2!{4*1>TIl*71M0K)#R z1_n_yR!vic=3^HCbQk(r!DZkk-g&+_2fo6bkpSq{88D9m+!+GK64?KZ(WMJ#T zeZ|(pALHO?7w8PiJ+bqB09=RhCIZ|J(Am+;Kh(<}>_M3t7rr%(1KL@zy90YmTpYqspds`R<24frI>J42!RoRU1AwcM_6d)PE64gzf zr>m!~V+IKzIT1^!{bIr$5M+o7NBz`@P(X8>WmFn)Mr zjseQNEJyO( zAPU%z4Eme>a}3y?e!&m*qHP}HT06N8bv++C8WIkY|@$i2R^GRXLdUjbl$mPnwtMw6+j(lE_=Hf5Q=Kh$Aj^Wo?Bv$kLBcfKNi)cBrF;dA}n zcIy2ugyv$#&xwnl@(F9Mtyu0{S}vf?#!quPn-gEHdUJhyL2#_oJ0XL>{p43BUdNJ5 ziPs5ay_Pd!(0;y6ulLA<1>RF6yg7Q;?iI?hXRCzXrK5jl?RE?^vFd*ecqC;|psq1jgJSST^BP-|Oq?N$cSd+Q52O}fH3jM_~ zsYt&%gwx$DK3Gg)+F@w)(ShLu=eixoi3*)h)_cUM7%!Y_;t{>k#XKGOZLMBvwZrj{ z!^twoET}QaG8V%rjZ&AAH&|`yld|t}oI1 zi;`X$rQ6u>C#?_7&-+-^%@bvhe&lIOiP%n$-xp$bs8`QwscnMh@+>{WSg-T08v;+} zCSUY6We;}liwOGBTBeej5n@Z8IdY-mQ2aZQqLna@FR41minsM|{8a6eK>Wo~ANBBv z#mn|5K6~6gLpJ17({Z2dfoCuO>bIV04{`M|oAI3Dv^lz6J#i*4KX8Y6Q(LfdPH@$e zaaJ9{%N|nycGYLy1Fy`7Q|-p7Ys8}T<@o;8g0s2RR{|CZ9Ou?*Qd z(&OYaW~_?2$=`eY>o)oh%ac9xO#ODvU`hR^fZ1y!+Svg~*T<4vR|oY-2(^w^rpkA` zZ_s4nP&Oxj_w;0 z&ohrXvmAdPoO7pb_UqVEa$fHNYy6tt1=6uJ;;dMP7xUgV>v>N}9PdpSjap7wjzm$g ztVB_i*WHTNyx~>)ijA1WsUYIvi<-BW2fv+hc$E8Q5##i@>El`7;n2kguZ9$BB5kzn zDL7A?yw2M7aF!{q#(iSrc`1(sWyUV8x2BY7+*4=2-pGB#N)SUSB%w0#MeUGc!OWW2 zZm%yEH|JW^@}33zX;;k)yb>&tYDlWMq&m@6KN+NOMMl3D>96bMJgZ~-FOwalFvsJp zfA?HH*YV}DNMOjZd9x*<>t!<>jNgiQdo66O`6VlgbqRKl)>X5VoodjWJcaSR+h@Gp zUhm08TNcX9$2(n~1kHwbhG7JHCYcZSJS{NV$LvP$6cgl@bvt z8A}oOM(0W#Z{+k`t!QT1v2kUFiorXhiz+ffH{Ea{ukc7~#8Lm#nj7UexFgm)8rStK zLykRUcsl&z#m1XCIa}K{F?}-eH2biIE4jy!b+?pW*3T5dv4o75McDP)FS|xdtp`5| z>E|+?W?J$5Sfs<5sQuvQ_~_Ablj)m@RQ>(LK67s2@no`+SLY6EADDY{cuvK@#6U0Q z{9~cVl|m|FJUyu=F%lC@?akNAoBAFMoY9<{zI@q8xKUSQ(&Hds!^0{YCIhK#Q;O%Z zesr6B1RTztK-G{Eh4vZt_^78A2jYvkk)RW7t3M_(P_NdCp{iCszFo5 zo^xkA^Eu%oDSIC%$dGx<)f0xUgMm zSX_16<9XOLYSXj($-L0AU%fx(NRc;2Z#a5`f@bgR>!g=+FT0ArYJhx9r~l@WDCt7awYX zV?9oW_)jL-jQ_9gwsQ=y6%rN2&@nNL=w}>{`>QCzZwGuE;2+78{0eR{aZr_ds%h562&l9XNC2WQhL+z=!@JAAH>M z{Cy5caQq=3#*XNMkH0mf9tl`@YJd;>ZYzfHbpRhcO8uIDFb42Uf|DWqNWh2d4?J_> z+;->y;kN)j+&^F*`p4A}J`or+*nhD7NWw(};RgUdGJhZs&H-Eu;a6e(!#wnlYa0;$ zXTS%0*1yIN*KtJnqF~a)_(3=R^1W66;eZe453+8y%5MdH*#FS~Rt$+BA1pZ7e&`pj z;jQ|Y1bjGuVEmAa=z@>GHKbku;Dc8=QP4NEt@eL8;KTlhdeHw?Ojd2!9gr)lvMd_8$*;=>pr2=xsHAXTXR17wkV; zbb$Zx8S!@+@ZtC)le|%l}`gUT)2L4^^52t@#_FSTtBei zVBaI$8A@ZtW2=phJW`JEy4G5}u%+kWU9DgPZ8UPJ1=27D2~hwX-CTU|eU zc3?1?SpQIWtL^s$e0YArl?Q!5L*g$1d^mq$+<(&kWx&_K`iK0ju79JQoAU?81P#}A zAn~68d^J@2k@8KozyFEUdkOf+{ts*8x`q)x1^DF)vi=|+*Lx7cR|R}Hf01@0mOdj z#Sp#_%fIK}pZIqJd?gS+oPUsy=>Ag-NWDtHR|9-lA1V7MF1qd-;KTU?pWh%KR}G|| zEckK`{ez=C&W7;0*)bS>Z2Mu^R{PHn@O4pqTmwM- zKL&hc{vc(zXdrb7IWU+b|Al{Rz=!J(>LHq2@m~P=$or2!;eP`B|EB$toc}p~xWo?Y zAhE^*zA9)xEQ4zZY=<}*!k-5G{eTbmZ}2FM^B#uqA8>8%KX`x(6H*R7{??Fsp8;P5 z8$Z|zw*33E{oEMLVZevJku%V59b+#d{!aluvVY^kL+T*>F2Gj;{$bxkLvSi(?__;CM&?I#2Y(S=&SGo)Sw;7elpunZ~x9T#3h>fHl;`1}X+$Q<}5 zE}B0H_-cR;V~2cP4e`Hs@84E<%K;zm|8W1t zb?=7`5dM3>R|kBU$93+Y`BwY>{rv;T2giAw4DsIx_;CM&T-g6e`9Fyu^(c8Z`LI6J zfc=1rA$$+OhwVpv<2nZrejVV$_ZRT|LktqGeTeWs1HL@A{g8{4|5F=~dPjLTfBz5X z4m9LBcr*9+KM{T*;3NK#vcG5j`wCK*ln;Y3M8&_=_L~Df9DiK<9f<((pAY!({D8C{ zR~>{u5BPBZfqZ!X0k3m#GK9~~|DWftt*&1)z=!<@^aI5zZTHqYszu^6s38by|-x0uv`^TU1y8+(`%ZFzl z_#OxsL;6b!Jp91<1O5LA{|w;6_QQ6=^9Qbm`0oIGFa@I^502ed?_XgKgg`pG4~4@BjX!{|^E_Y(Fyp zaA`ZNgS4L)kR4F`tA=6gKZons!59$#et@rp_5UaRe-H5C`lSGx+n_Lx zhWMYw#t-{%D}9LYSrjoC@CXwH^RWGJ4&!17UlZ_kv3y*3NF9WK0q{W+{&@cP06v%k zzxGc=8{)6O{{RPr(^ohar@v?^p|8Quh<_?@1vx*!vaPmX8Sr8JkoPC^=LFz`M~Gkj z5BC6E4T=Ab(&qjR=gyyuAH4a&`wyHu(EnD?KMsHow$NYghxd-H_TN>&hw~rCz7<2- zKY)!Na^d+0R~>}EL*?Jk?~sp_L%rV_Qcn-?;qwpV!v4ec9Vo(&0DL(AVBC&|RDZzVt@`ipZ{gZ^z|Ft<$qw+*`!}u{Nc$fEK3u;r54l`W90x=AOMnlKu)q2b z+=p>CgwLz?@At2eyw&-C9Pq)vU;c4+4k{x48vq&3f5;_-KX5dJzY6%^2pUBWcyR9E z`V4^Zl@4yk58dKAcCaqOKM(kb|3BeR0lpH5AJM~A1F6rYzWMhDup^ZarA&43T*9|6|UR>yAx@WB-N#fNQ2bp9@Gq#TJ~O?z|x z!F$i2@FM}=2o*n~i}?9FMCx^8`7n>`*g;K%&#klh{u!=&*aoB=*7=wOeE9qb_n$wBpA#IO;rJtZxN0Evj{v?E;3F|_HU5Wy4{o8q_;Bxn?ZCwl z|K9;0Ou;C~A;yJ>t%LBb^fu3*uo$*|tL@JOe8fLoJIFXfz26z)e-iNF_#wWje@8-H zL--tE^ML1HgwKzv^Sh4--x2WP`vbUt!T8}A;A*fwOi&A1zfcDnL}rkgxfCP2H zJEC6(5&8x9oL>m`j$ddD5E>d`Jrj^1nt}ukBGfa-;t_!Gx+O@^&mGR0ECUFy-^JoREZ)arITjyau>y+^ zu~>=4DuCNTY5@rvM5x;eGr-UY%iDgHZX(RLWAnd5Sg!+H4{`lY&wu)jAz zg7N(d4vR2O_+M^?PAZ))lK&UT?tq&2#BZtjHgx3#X^AO=jMQk38P*)jSjz(Cd zf-OfQ^rL|-#|2>=+SvMNgynjm9A47LUWW)j!v9_jG&I6E4}o%sMgSq-6k89C@VYrD zhnFm{cm!JyBHZ`wuz85^qdoWm``H;={wE0Ial`TjUQDo=XlF(O>X?=Yap61OBgb!vDYLfDNh*>|ETOk^c{V z0zEv;rY>5VP}Kv!PrBci=lWF>rM;BFhIU;3v)tE@8X7S45%8v7VV6?R@+2bARan1S z+sd=ca@Pcbuij@1k!>!wgUs&fvk{_n;XMa2!krSSG4zG3(&zIBV%7;A>)al0-!Zsx zGF_L6^Y)jN7Q?$E;=6nt&z3jtRc^ZDy<~rVAij%@s^sfRL>^g{>x26!UD(%%5eA-~ z*v-0c?@6{Cb&qM+f>?`v7zcM@na=9W;pHbA)Y;{X8ry%ak8Xc7 zr9z))b@aGjC~+`K7oN!wBfR(gD8r@H_pR~gG=vEEk&_h`9ZM*#`dPhby!M23&y;~{ zX>_jC9Twg1hvk(@`Coq{epJYLYKQFLdbZp#)?xbON4CU0>uVOtoEx@gF zS*(~MW!PIVQ#0jK!%R`x$7!)=1>QN;Gi$03*N4nWM<*8cUlpaaV4Y|nQ_PCIpwbEd z=M>1e!FxDjgw$p_N4tw=vT8Ml7|9PFcz;&@rB`Rp1D|yX{$Opg-6VsZoqUfy?Zh1J zwC@WMdHC_+@ks}1dkT5;M9Ir?^oj6{j_AU3CSrsdEk!c#9Q!8K(r-(-s**B3rm;3R zNX-!Sa8z?EIPk(ti+Sj?*|$BCM_+~&9+0S@H@z`@wJmF+)ADPYrlF`9K1vrkw?b{g zqke_1mOi_089eb#EqnCo+#MB~{2#3YNs>9sA13dtSDhc~E>tjcoL*Cw$%(eCJUDmf zyYhj2llwQWc+DEG-sDH=k|DuDUD4hQD!Y@7w}%!uNZorS8AFFo_pIt0-1=stb?o4R z?c!XWYvA!{$=Y61rii?nJq3qKmdK`4FV1_3?~qlxpEZcmh0n5x5muL-f9ygvUL729 zTQSp!U?ZLGVmMuxPr2=BEknJFO577IPYt_vMpK&dv1ymz)Z+@Lb>7w6T5^_|p z@DN?4Q?}yCcDDH9888#wo$)~JqOb4$<^=W+bZ5_Mw-s6P-)HfhQ{|Mg(`L5Zc2HjT zY~)AVpj18q&-?Hh6q#r686Gi0lDdmjd)M@>Z;D)4&*Q2f^QNa*UODtc{SLv!-0m_N z3Tit>*W)+e-D+KZ`u62$d>V>=( z@XmQNY}*xS$;r-Vx^rPa<$aYXHY7er6n?vrBlQK_UX5>5+b*LF=xx&t_lneA*q^971&bAUAsx{~?uS zzGs%0{oGeQ2Y)7HF;N~Lq`JStEp|Ft*g}pWIXgF_DdGp^AmyD1r`@sWbxe!aO{JxG z`LNXAyvD`H;#Pf0`?yi6YlCSQrk!5wbJ)A4o`@3nOFZmc!@OYxf`D>QH zJLqj(V$eT!coY>ce20t}A&bY|+&8a`*pp{FjKlNDVuC|xPnBU(KZ_2`%FPg`hFWA$ ze_n42z44QOy(#2KX?a=Q%!|`3DawS3gbx{xw059$cOs$y2|u)Z3O|+bDdRC|0}OKutt2|FpX#;r#fvm!|Km;t3^n`Ckd4 zba$b36(ZP(>4bWyRTQZRt|}iemt_7}_$`pL&-~^?7WcLBQwJyH<8lSX?$cPka1(8; z>ZyzUsVGXO%FIxv8An_A@eGCbBo@y&;%n{f5PM#*>3FT43o2-`?e~{J@ zr;|Uq~3={w%v`(axR5sCenox^2V*Q45_~7gb*+ zaS9!o{&9C~hBAWsa=WGuYwol5kfn6Lk?|Tu9>K=50m;peF0axl#!@b@%dPtQ8~R7I z`_`az8PK|R4MpLBrv&aW+6f7oOH1w(9Q9=RdOJ*nit%l5{2L`!3E!?S&QwZAe9DuC zKW@voo%qABHeZ1^e~Itmf!JN;?I>MFwC>#bA4vz&-*fQyJ!6Sk7WKR*@=;4F>O)n) zDNpCb#@fl*_=j4Glap%^VGlXWCDb=w+1$G_p1hZ%_!j1g=AistlrH?8H)4cShWU}2 zvf)ij7x}Cn$XW{;@zt`cnMr&s4{uUCure^~>|9S-rzbJqq%##jE-$0~rQwcbPKu+G zF|ld0RkCjmN*BH}L5y&zw2zj6%rYk8K}(;aF#F4wM^%Zfyz$hE>FX>qdAOwC{|soR zqR=NxGGnHelIt+&Ocy6*AFrGGs+e8gou)5~(q%zJ0TN;+*|jh^1)S#f>-FlscYj=T z*8g~l=#;;Q{mR?PPyOG&J!4&Pcz7>##Dn6Mvu9)Wx8)LXE*Z6D{<9t{uEG}AP`a#W z-KR5$-8ovu3T$>%n8uq|-|$?C?SG!$c&#q&;$;=pNop&qaN9+xH($RpmEAv(8JOxs z;}D&`7+YR=htPdu<}iAH*p1fJx|f9+q@2_1OG;>R+E5UDt0fjG#!SKdJe%j1wiqq{ z?Xr>gdrn!(Mc$93IX#0%aQ&SoozlmgQY{U}JLw@G@=)=zp>=a@B8?brELy44w()#& zCS)cl$P@J(KD_-)!D|o3%gjWrxwM%p4of}fzkI$l%Cx=X63>bK96e@^_4h5DJHuGe z@v@_JAK$JdzP*%nu1Uo+g@^B3o6o0|&ISF39dXp})2^K4e;xQJzk5Y=zSR4NYX z&-DydF_-iDWY5LEkZ!-s#JqZYsegEdk6=oYoXJAP2Y-o;bK;x>kud#Rrt8~i>gOMG zgekNyqvGX4>#A!S9Jq47G`C)f>TB{V=gt8te9P|>!M2<^uNP872rdhAm3f_K5d84; zN7XQN+E8tIWS@S}%xCSS?B!8R zWw6Jwr_X)mgt|Ut?2PG?h+9b?K84xAk)WbLSxcrT##^n6x0+(8ii&p+TGwc><#Y4H z<6Wa?IReuSdKC}z+~ZF;!#y!i?QLa5Vn=i|!u{jt(SexhuZEM2A*ssDuGJeK#9SU2 z&3yexLAca~(%p;JJ)+%T*nMvN#u$&2xOCO|N=LiCgK;M)q!y~yeLF)p`oC|Vy+>bs zRP`)#g0Dba?u`A=_q^*RgFYuucNd70__L#Q_n~#8#IhC(bScMwKDc;mdE;@3%5iZr z*7RGtW=&Js_TO$^)OuMkB1Xnce7N`1sbjKF1n3o_Ess1mQ5dM~-t$?!z7D0!gVv3& zH`=d#R#%?;$N;NNO8(0N#Vbl`W!(haH~WKlC~Bw0mXzkX32UktUDGtE3pwb8)lU?N zEWPn@5|dEb=fd|LrOS)fJ=wcIt}v@3GF6M;$NTh0Qrmc!5+)O#7jrEQ&9N+x21Abv zdRL`Hutm^540+mW>3*IqvFl(UbEneyv#0=ZPW1Vg53S3~EN5ZZezNn-5&o!R>Nz~J zmsV*du4efDB~JrtLy9X-P(CfIVv;jW$gnChlPj-cD0Z{kqgKCne5cf+gx_iSP6avd z@S}A<8h;sCy_Vlo#Kfm!*`uaJaf^EK0Il%8^gH9@hDsTy%NeGU#NO3Ph)l2TFX}!k zN?tpBpw!|zQ-M4oJ7s?ba-M|GZUSiC_e=!GPh1s#_!>{-$(T%2OOX0W{Y2+)CHC-Q?@s%0A%AKa6(FuOpTJg%`KcY8$iFmHyW<)E5D`>R$){r&eAyflx`=!BXP zijTg#+^c>J)ek~wU9#!O`Q*@|`HsDlEqN(yVXQN|-x9Ep&>Z@ZG-%2mm(5n7s@d_g zMy6H5Jy1wHUfgZ%IXig+J?tkfFn@n)aH+ortFEmHNsg6D{=f(fJUGnB3fT9>EE zdYASxNm3-$RCJm|FmK|Wy!Ifg>-XhyjD2<&L=&(M7Yy&1xn#iKXIA#JvqjBguy3Z2 z@$j5OLI8cO>=*buB&2^u(YnTi#I8nN$C*e@*3EI#(-n7gJdRX6+r3@(=xigWg7U!k zlR0>!&QiU0gF#_+tnOw#Up>xKwk_5*(f4!Xu|Gl2GcmMoSS+2vo7w*BWh&?TzDMj2 z>EHc^?R}Qfw7LYoI>&Y$tAxI~^zkn&Y8nG3Cs-Bgji%i`o7;SJeb4anqiZ+)Y&t4l zakQ>fu7bz|w=;C+z7}h-RkyFap<~Z-{SHWb5bCIgx7gE!8zU?Klq2=?I zlUZTR%Q?>q8RBim2eJo@nMHOx3u+RQcZQ`{+I7C`ZA70R_M>&(@T8SL1qo>%uZ$}E zK+TumA~Lbp;Hz5GYZkkmDN}^2>3hDpoxW-0sguam$RlNY`(~X|GaY9x$*#u~%)Q~= z@OM|pxJjaQS&ZaM)gzN4=FH|PROG3q(8c=68@i~IK88j(KZQ~d1n{q(_iiq__f zanG}wNSJ<(x;9>Y@9DHRkNT~AqTh4-jz-2!6BFen z1$&LRsf$z?ypIpZwPkjSqIBiax*vU?H$~1K8&-d3C(^9xl_@K__Jn4CWA64E)3T1B z>*QZYY-gt1yDyABCE{=;zr2xWR8Id``m`p^XV*5-#R^T7t^!&&+c@CaBjdrS%Ni^^ zq*)y^I#1Z_4z`+T))97;o%-5Kaq2<`H-WjW-rxZtQ?l|I^M^yU`%W z|ANvzfY!w`{WPKy6y85Om(=4btdylO6>ju;=~8o%#D~n_*PL9uIgeE@NFU>#OFGkg z_1h%_W09ROw+vZbOr}EVDxr1vJqjD$X@@Vr zUqV!*(WE*la)X4EU&g-5iV*YsN}tS=W%=Q(C+Y9ZJ_o!PRq7&CI3y738+m&~^)dgY zVj_YBHk7V1S~r3J42!7Et-v2_?oC`9zJ&^M&p8@is?9ti&&y0Q$!L7^{@7mfH@dm+ zh%R>HrEBj0Tz&PL)REmpiN4X6b4TLQ?_pHXy6b!k6GI|x1j>;K>V=9fGx6V;6?$$f z%@Rhs>rbm|ROD5dzTyk?ZFG9Fv&k_fSB}Q_wbfOTvS610%b_&df?`y>s%YKO*c`); zJ4CIkV@H%SAAI0XzFegLF_q)3_fA!ZS&bJrYFGB9Pn0XU9>-i|4tU6#TzbLPl8{Le ze-8%-SzMe9a(;mC*VWLv=YKT2Mk?BwKD3liCSQIb6SSK>d{(-|`6j*BbJ3a33yjYw zxOrMFUfqe!W=InsZq|+=3TZdvr>hJ+mB~S#(}0Ti;D6|jB&^rUmm~|*wa}AR&qg*p zDV2S?z>|KLBEj^F+J`Yo%M+K2v*!=Ju#DW5-LYt)abks&8LXmsuyXL7+HK&PU#VxaSb+Z4zi#%-r<n_5Uy946d-tB$_r9x{`cd!?l&&UPcSs;gqdofU$g4;6 zr`-a1&4r9dDpvFBm+D_cXo&P(kSAb$#Dd8hEx!4sx+~52z|=X1mG&Pb28G?J1wEcAZKF`6CTlrqmJcsQZ)=;|IXk9~fO`Q`%9VcU!mcA)E8(Gopxbd!o%ifMF ztF=_}*NKGQ+#c9s)lJ?**@ zP413=*stwb_qJ(|Y)6At66u*k`h4>2Cz?w=4(&*vx?~|9m^XYODJ4a1$DZh~P5zpU z-(2@9wHcw})kW*JpF4fe_I6<4_K;4mZvjgo(QLFkWbe<|<1@W^_eofXO{ne6@~gQy zCm#u$?hCiRj9ov^&Si8mIP_Cjqif5_NYM>qo1zX8|v1)ct6R?f7$d#OX5JyIsanui_SrBj(Rg( zXXemR===2aTwX&~5=rEmC%sjkibW$TK5T~@DpmYp}od6fr`JbRp(nlEfgVz4WAr@-xP zDBVM7UC%5ojg@n$R(j`6xRc$Kp4~sDGCZFs?fjam$n(_byuASaE#Vy~-NR^Ixz^#7f&n+PROS~iUXIgPIVtO{c1_qTmB{6D zm%dF;#bnVW)-45z$9A1zcr_-|K=z~I=+SvUPtS(oxVF1))F@r}ywC`9g>NMLI{gp43oJO6a$=WN(+{iNt0~5BWUclRj}r;D zk3CH)`!a*lHAX}M655~GrNA*wGorJw*M|X5c$?5V2ar?Ki`LAEn5;LN!i=35yw|=9?QB;|H7fRO@ty_QV z>_Kw-eLAFtw_|VbwPI?0w#S{R@G^}gk4F4_{D+JBKVP+y+z<;}+ISG2T3j{0q&VDk zy}!*-q?UUwaj!qT{~+ta46WP6TkwAFaT!0YCHwl#{+tx6M!FRh-Zt$ZfmbdUg;=Ph z)GCMO14@~Ktw??E^e`UaO>Gb%^RSq#JTxs!W1WsZmzbkM=)nh9%ygOWj3&ruzWd+`wY|!|Ci%PNU~kgw+8f;?}h8WPOKiW2aH^ zTA+2GmmR;wsbp|uD0Ppjw~HIkq31R=HWdbxhgd9z<9(=n!z70-tuEl_1myQtiLOLV z$Gv<@cco&8NJ${U+Tj8%ElL-D{~IyFgEaUDT7M)iEP7uix9uQe<#XLR_~Fb(kc@FR z?_+Vr%lnQI9UR;5lqpN;^S+s4{M`2R_I3S;iO=j~%^GBRdw5a0mWU`o!hjEthbb|g^ zmXO#QBcO!RJ&M-7C-lNR^}bQ|;wt#xtv&Pw0fvEZc?b)E<>emXbt=7q~N zLR0d6eAb7x9nimLIEL2U?bk`hx{%T=?>S2;G{EJ2^?md4%aQhkv*zyGA7)i_U_*$07Z-cT|V0 z$))bA>qT3H3`(CW4Dyuy*@ynUh#gwjV|0B9@0jw5J4uw?3w+HMOog{bZmKJDAC`VQ ze%^W9fVhQjs@(Ib*IiPMl((N(+#7UBL-u+n#R|!YuZU>(Jwo+^Jz7_ABzNgieQPt( zQ3kb}&(<998j@l{ss!!U1k^=jrdmy|1U&69sh@dyMb+`gY;~EAER^~(7N98nSBfLjV~W0^jPxw->8k9Gyn8<>e>SjPl6G@eRT_-XTLAr8sj>o zHc4mrCe7|r%yHf6eXRsmJ(X^$?mai}pmZJ4x>Z(ZW$eFR@%Yf;lw8<+?sTQymqCB} zbK|EjoN{5)KP?*DDly5OeYfXBRUgqvo6|>(zn6Pl+jEs{cmMmm8o}s!=7iQg8{s}A z>1sFNbZf+IyX@StuYtE&9hmDEzmxIuAF2!uy<`1suaBOso{g!k?%Uf1A_Hrgg#|*C zsXy$7hNLu{(D!3!wC=*f6*}glEyq_!$B&fMH)@>pYNEeQB2w*0ke4Yzn(fOvQ(j{A zDz-!94zvE?R2)M@LRneE4>ERLl;qpvJ6FJ<7-PkY~biX_WxXZ)?mx3UGVPWRMTs-f?ju4rAt zds6yVMwb2y>9u>t_#WDqa<1OuZ3w%?Ku4FRom>$#5Obg42hWevUFB&L1TA7mY<;iM zc)3IuYfChcOSDd+-|x7gb=4wtg|0eg=QXo3j(@?kRpVl|A=ydu5wVSRdNt>xoY3%-i<#0x}$Zqsyn@s2{nkq4Ewj;B`E%K z?ZJt$boF>Q)A$tfo##Vx8olbHL*Ko}J4I!EzGIBUS4a6deTE+w-NZ?|H!kKw&r$vB zf!19#9kW>M@T?IUn+lUI*)De0%HTA;yhy{BCk})6!Y;FU`O`aQ54H3yl;oWz&luBd zp}cqIK;QGJ+T0IcpIwngKNotUbzkXTjJ-sGf2Dx?_|9h^Uoh$kA24`za;W+A6t1qNyBl`ob1X1%Q9JqPy0&`L)=|9VXQ?fn{!XVGqP^zN6I ztX)vL-e}$3&xXkQC(GKr-jb?F5JcF--RpAyHd0W3gznMzxxQDN>7O=Cv^q|7%n*iq zo(|_LY2xj_NZF{d`@_@=zms*#=yRVBTK5r+l)DSjrCXdw=oI%LMQHQiWH!PlwNt1Pn zvts-G#d7c7I2LoBCw+0d9?T_;Se`vBWY1eQH&$^$a@P@xWo3s5ZwvJM-vG4k%)K`@ zr8Qlg4+l~rFr~-#x8Mg_p38o1*<2En{)8{e&`*{qF7fLmr{&PXFt1ifx!eNxB6V6> zqJHuFtVc~I=--hg9yROWy*>?dyDNKXNTn!R zA}u~t*D8NhVEBChJH4Rn2%-v(a_}4ttu)mN(`X%{W5ww74jb#<9*v*P(QS z(Ym*YXQ`cP@|XN3v!kD$m+N7WzOJ9Uo%n1w?{V?qLS{dS;Jg(p_HDz?DGc`t%b2_p z_wzLBSKi(D)MznZE_7lHr5l3QEqmF%d+nOZ#(29t?G(*r7S6VG?G^CFCg&nCnuPf)Wz(rMLoT;aq@m6~1 z^jMU4D@8Wp$97`D1Tiv3!b4Y`^b=6J;b`3?MzZ|t!kC}(J8n_5^)xf(p1yb2IH#Co zI`p-_NQAXbOMm<&qYu78S>B0i<1U(>&R5zy3g{D*r)LprfJ_kk)l$gg3s8!(KxanHN%`BBp_#JO1 zdo4XV@UA~f_c&UYZkOXextEOga|=`VB1-!}Qg63Xk>F-%+-eCYpBj$)vNObm8A)AVwH^ zx?I`D^KhA|qiuQc30Y|yk%5Ba-_B3U9FZicn6lX0654&^?MFt7;z#dP8>)Z zClODUXZXH}VenHSpw<~I| ztR%XHD(>XU_Dl@sxO(Ti9BWfJc~Oer-l&AI=<8vcAH|VAy2AcqpO*1bhwr}Zk-|Uo z<3YYED&82hZgY!*^}6UqvrmO?a(AiX$tVq?t62RmUNMmUbZp1NCh;8v0=sm==#AfR z-~GlOvr0Su)AGkY#hcxM?^Da`re`Klx+l@Pe%6n^`kdA~>mfYaNq>5$ikHnh>WW7^ z4ljnyM{FrEf;((`C`^^a*m$FIUWqbkh4aq^`1~sI*r0+x*+B&3=eQ>yBw= zmJ^J3O}^wv+@1J6<639%3B7AXu~*(r6f$KJnW;)O%^i0c{T5cmZbO!7l(INsHtXlN zXxUSAG9Xkyh`}BeZyZ{;W>D5eSIooxNQ3LWwY5*#Hl4}56c+4XpOj27*sx1)!)NqJ zvkiWAjXB^&jDzm68o|fmR0LVW#O2psMBSLRvqkB~qjf!LX`?u~6g?FmJV;ZpCrrwr zHeR;a!6-yEs3rWC^r_12hQmsqi5}=zd`a%uuVymc%Wky)>T3MiT9wsAi`Ts9@6(<_ z>n7ST6S^|5zI)L@o7=geQSJIp?Ssp^IQQSqW%ejaG_-lGg24q}n~Ye&$c6uh*12$M2B#?Z16}L9d_uc7+kG+H;$?7E^EdHI>8}JtKYTfndh^b@?BTxFN-37rxf#Axi~Xrb zulrCq$J_8SzJIA##Urf!$VM6!ZxUM9>wOuUxUfxaZOXt|y~7ltO_v>tKCaW6rpBw# zpT9Jx9=5PppjqZ1Z6sIBYQPooRI*JrhT-}C!s zKZo-uqvB0L>jvAI3h>;?ytG3zkv;sSK$Kx->1cQ_!*yTVj5Lu4X^f7ZQYSCCWxi4r zrfN{UaH+=JG0Xe@+pMmEJ#pde=LX^5P9XQURJ87fSY~d!&x>Qk8e}2slikvvqs)-9Z?pO;yLw4~V$vuWIm!E~)l9XG0%6aVtiGQDXe@2#a@PG|H`aSI#v~D+> z-8s7Na}5n2F^dM4ZwlVxRTRpMBuCXhBMw#8R!?}f)|Xh@ANfUH@Ze%W{54B;wI0*+ z%vn5UiRTX1IWwc@*;%x1oht#&eE7xpJ06*yrs=Gr(O50JK`!#7~d=H{Ymd^>3!y$H~M^b4y`*^%%Lv%X>h4?D(#DW8?o+2 z;%gffbc9 zE|t-CbMXfUZao|&b1BixkBoR+hqoxs{o#~oK#6*r25DCET=UUk+nnij2%2y=oi)ROi_t3C- znV#Kt&xv^P#yggWltG>~PrqCmR697BW;DCx#zHFC6NA#dfYz<%(|g7Du08R1*W|gq zwV%^#_1g~F=+Cv#$&q#I`l>F44q06@DfOB3Z?Y5H-O#q?sZ8(MWbKV7OaDkDreZ<| zrF#*r>vvdzn5w~lSGt7QuqMCZUZpZt}{SH&}p*C?n|g&T8?j@n-h z`8q?fZ{@^X?xJ1$&T!K3=uhMuck%2e;v6IGe9Gyr@!P7Q@5kwA-2xuVN?*D?cMj7u zhVSWS7QM|=;=N5z@=cGw-W8gf4Zi2fV%cX14)DvX4^d<|#(%IPa%eWN$c;Pn>%w8|aSStm!fAKQ5Qhlsj7gv8eQrOcG zv%#63Z_hA)rY@~1EMoAD;@MyE;{W>p;AWw9mGz_iOMDkz6`yA&I7D)bbcfp_Q=hi# z`tDu+I&PzUue8VLMsx)z4~5ZOT=5FHw(C~1$$06!0nx5+15sCr-@V25FN`-Et$RLS z#cE7#HBe&TnSCY=?jrox5sS9llGE=SR~4q;qbX7-Qswn*$GmwX>JV?D!x>wM;RT-{hR<~x%$+)F=o}8Fx&74SfQ5b%+QSvoY>=aAjMZ=k) zPi$>u&rXv+9Pa4T3z{Yx$eUyC)y=qE&tFYYpL zQ@QRCV9XibWJUXRSCtT}jc*X-Ip3oWV`F4JNN-eu)rIlqqIGAMysaz^_wH_4y5n)lDxJb(``bs(A8STW zO;I6e{`rd-0Sn`Kg$7P4;_$ezDSO0hf1T}Lj#cjff7o8X>TB7RjT zD{0n!skpx1qrT<%E8flXWIkFqp{iPTA|-6#8i_ztOGPkAOd(xTaOH+1do%H6h0uzO z$~dRgSpgY*wF6!^)vo;PxE@*DRCvjE`=I11wL*(+o_-%UuH2yW*>{wP3h-;Jdw#K))azmF|ld259J z{_l0PZszys7P4lq;PzetYVYd}mlyDhO!lxS>>u7H|0+ZEgl4=`OK9HA4Mp)9l_6^Z z;;0>kdj$s5n12|CFuX9+Y50nY_Xb+mbO3*c(daPk&4^=fRyKV7vThbpvi0_u&&XUc z+U~#^dVJ#?f8RMGsfBev~l-+A# zig=3$o`CO=vXE&C36V2F=d`EdO77 zUjY|Y_pLpEVi$s)*fDg83Kj;ah}}BC00RSqGlPPOfh~4mcVGv0Aa-MSU}KhZ*1Ze!qMF_xr%#}YscA>v|;b~J zxArluKgO)8WN~(W=|kJpbxiyo-t;e7vT#JhmqTYXxlnnC`I7CQn@!7KeC(yJuSXuK zWwP(QOt{{?UMSakL);>xmJOD#n$YWV!GzS14KHsFZaaBQ%S-!~%(i{^@S&_@g{vXo z9hS7~AWOYCwDRiS?;Zy|EobIaukPoDM_V7FvoAD$)CQs4QV$ZktU03!pX>2GU#q!e zFHLBdxbDEjeQRr zrR`!Cjw$Va@M4|nr|lGDC1r=NQoR$7k2ebCwmo9?+T;7T{rS$_4QLiIM*Y=ke3>t+ zSGv~d)Ai}1r4N3)O{x$Var|qX-}|~NmDfL3oo%%xW~-AbQCZ2TNt4r_RR#KP63X@2 z6)<2=rNF60yFPdCQsO|Ym4$2ba_z>nzWLZ?qtlCJlUHOmR&?9{{AH=Yvi+ttFYY!q ze^9?u>8bWXFw@0Z5KFZn)Y+aveI1&1nD z6u2rHw|ukvg0J(ttaDCWe*L4WrfbTjR>L~?T{-9L6{8S`BX zE(HhQ`X2E#d4X~NQJp6CO9)vSl0VI>W`4IBO~$17*Lm`M+al@1*|JV{9S78ZHKKpf zs{xl+Pc7>$+}E~MD7QiM8hdlkwI-3gca#4?0Yqx(D=(|lQch~+sp*05mG~bZ)zR)t) zv&o)O1$TCj{m{jA>1UtP6+|ARN0iA}s`NFDsdDA=aCvNb^S3V-ihN$)eW7sd>a9!{ zj$5`1loz8yljQ@T!x+&cFB?c{qqeiuGpqR`gk&(ms6 z=;d0?sNT3I!^^%XyT@z9(5G+4xu#v&^4oG%g=-&6T$&SDCFM={0C)dIW?VnSwd*^D za;p#9v213|l_~AECzor*7x9 zcT1F0;J*6ah1NIjCA+7rx>#V}T|&9Te!aVXw#nM1QRE0u4_?&tkFFUob z+J9}_9?#lcQ^yXwQ@q2KS-VD>E-31HsdWCGOUj2dm^wWC?3}c#qXcpjgmU|TEkC96 zyiu1*b=y87X;e|?jXlfsHh;e6SN+B@_d0lYEkEh=n+^Sbx|A>dvO4YaA$=~MDt63eJg=CK1aeBg)+Gkg`*&OU1{(k3A(@Ae{?5?t+zifWV zpB}a)S_|~uE0lZU)Py@{QW6fg|I#zQ_?dCXmaZ8#@<*JLf2mPVN*%d;{IYVWN!a{7 z({^;4?|!-E^z?fNJbu+}KXuTPFH7(AuCncTSApDpLb<)#eu?kfyT#SLV^_U;cHvNY z=Q8D*EJ<(R_0i$kN+JCY|*E2o)EI)oY%=ySv zf!zHP2Hc>cccZ#{-r=^t9P^q~U+xd()D#ja=9go@TrnUEyw<~U&S)b6F13~T>s z^G}x`*|64aZ?;<8v|(_!`sx14a`$CPUb8z(wskCKe*3I>d#|7|CQr<}@3J{nstJ?N9j@7qZnyaXD>hIeDV_ zvkPx;yO;U4u$ZDq72kcg8uhIjGyTrUjX4=4+-`T^7(N zqTFJm-NOpqYi?!vsK0Z^j5Etk+;&P^8v7q|N;+6!#(Ar46WqM=d+#06VD-fnEd%e& z``J3?gRnh2B9xoI%JqXbb1S`zzgx0Z?=!Yu%g>bVJ#)$7W2YP&tTg?3t=9T>-xe1r z({Q5El5ZQ-3xki?Ej;PMW^Q*abCs8Q(_`B@~mPa)Rv^P`R4O`yE zWZTO*J^^0JqiN^b_;-&LACj4vBvkgj^5Jvh_m^rD`NYG0yt~VXL|$!~Z-!Ib?KjH` z?0ZxwcXxy+rDB7)?``eZ>~GceoJFnE9dD}>*FRdTd^DiG&59G=n|C)5dtAvM{;1<6 zqq+Mgo}VBsP;+JryJEfV`#g+)R~p*y#qm1*H$FW3EB~cuBbRRUO?gmDAorM1ZmYPq zl`Af7QMAnD>&wd?TVgRfZor6xCRLgjN}X1r_k@vgfgbLyJgp1O=%tW#ujuv6Dzv-n z;6=aQ^l>^c+v!UU58?Oo$Axk|u5=yQBj5cK_VsJjZ&AefK*t!jcU{$EI$qwhK>n?b z^CZ{c1%-CkxwpJQm(P1_UFR9?p7CWy4cB%DA3dtQWxL{%aKF(Bq1@XiXSuJt@G16G zqqKGL6$k7|h#Y(5dS-!R+r)`uV-Cz{|M5_%$?*+7t$kZyrOD$!<-%_Dixs!9*}1aN zRF~9|0R;yL>~K;jH}jaY`fW^O$0zj)w%b3gVNy!)E0i9e&jQL=|6Z}$~oEB@`nTC z%4IIT6;%DQ#hba~Cw`c>@9>jN``?GVjz3gdWz=xT)D9DE&1)5W*mT+DfdYNc3gy1+ zrP{aaoPX$<+gmSmtyU|tt>48hK_`vUgK9NB6Z0(4jcH>%!N z9VB|)W=V}B3Bx?@`*)cmkb6!jxBidF7nfi6khH4PDSC(4^T3mG4_a@kI-pD0dZjPP zyDvBupSsVMz6ZW_jK#p`pLT{uSzC% zbE?nR;8{(kd@?b%Uz^yieM`(1z7 zjZKNII`r0ncazt-rq5Yy*5{%4-fg!oCoaxE+P&^en?25b(z~4;wdq!(qkW{R%&0P( zg!`^83FY2cIs0I>xhwiLn4Q1+P1k*^j@ykXzir^p6@!2J9qD}{_Q|?hu4QA2#(YRw z<5Vc{kcyC=Di6ha@)At;whPLVixRM z{5`FOMV0O$&r>bUYJ8k^U2&t$oru8r?Jqsk*N-(Bd!*T#4RN(6)m&I@q*r@^+{;3_ z&f~@H#srVC2zy*-_3gRV;SWCrulPK(WSY~aduI|qjC)pZ?Di!GckeD6{>W?7XeYBe z<1;q?Ug=P#SDiQYr+iF3EnGLfB9wb*-JLQUo7l#c+Fa}Bwr*VqPrI}3>$Hjc?mim7 zdPk*q?n~!Cz4LjZZ?xsQ94!QQ>7bqR`@C(pB!i6e7Vi*ZyA|W7mau@ z?^96ttO0JFl4c9r$!kKnV?L{D_VPZHwD{SL4o_-4bwA&@*oB{_S3jRQe|*W4MUP+Y zc|7;F^2b|`M)P`{INUk#aNmZWqxYWwF=XrP>fZLX?+e!puM6dNcB!y7b>7^a)n}Bm z_ugGoHLt9Xn`_y&lMfsp-+yyOmC5%Z?kUON{ZdoU#5egY-M@SO+=Uw^z3z6fOd~(L zvV$Vi1o?JDC|7d-S}Ci5o;Bm!yqe~H|H^&Oa-BV+18;kcJ$Yd4oyQALtR3ika8TEm zCez=PRfp^-tL!mMRPMy}&cW>mzHw9U?~L zALCk>1=?LV{dgH6?DZD>`cY(kGu6WdlfI^xcOAMN55 z)6exXHmXw)`3M%k> z{O+XIUpvKq*fsCmp+vWyqClrUeOs5W{l;&`pfAT#>?a81-V@68cXE?|-*>^`#P`W9 zHsx=+c(ZwQ^n#{MOC~h!AeAT{Upn0WcBRqXXJ09PIHmHI8e?m;Xp+7yJmONtdDcs+ zUsyMPia_ptq1M!Oodlea8bHNa=e#WDL! zHa0EU?D6zEi4*1C38fsRu4589iPv?BEGOLW`9LVw!X(nRY+9|9hi?=6Twi(gawV@vD>l{*?=gRS<(-`p7qscSqWiY~%42VgLn4Gkj8y{>Ayx$oMK-zFD~81rG%`n9)C-?%K$H$^BnXk>#% zH@+I3+Ub0-Vfy<=`9CaLF}voind8rU9w~l(|I^cfZ7R(!UvWw;i@7Z`CLebxbEsd; z^Knm&toN;rJR8=pj&MHpu~2T*a=Q{WOua*s_mx^y-LdEW8k0t3ocx?BGN~S4;MPlH z_0feJPdLBpeXaY>Mpq9chfVCfzFxiljjlgxBdOWfW!VWwfxb_Ka#vU+uH6z@%E2$? ziDg;ab(JMMe!4c=ym3kFn+}(c6iB;txl3@F%OP)0UEL+B*&(x4@F#DJ1E2cuXg>P+ zv?o(iRFwsCp92M#*^AB2 z{2FH8t6zzCgYSLo@okCq>)P%MWL6U^){V9H2+ALmIltS+`BAP9s-E36YTdXcWe*AT zeJ+&y>{gu!zm1c|t$lXpR?uuoaOVp}SH+htI<~-%*VnvzZ40!lkUo9q@xdoXkCB~Q z_Rwwe^)X{F4R9LqaGBqbIuB;o?urp+Ih`P;Tu`Qyafnp>9z)-e=J4l~ub(n|BYge|w_wdH0mhgVh_I z*Ke=>ywlu{7iwA`8n>WVRQ|r!6Nm4ZRsCzq5ig5?S3`yRz7onk@V)MZ@^6~F`|zQN z=fK(V%R^c`ZvNwJG3kg&MxTo8>RrYtxr^7j>R~(XcG~?-n$)=UgPq$ZRr*#U@x_wC z2Pb;A<<_0JaqMfM+$wW_JfGHP>5(>7!-A%Ydseu3s*v%kRIXC`UZfMUZA3`nqE;N1jxYV2g| zh5MD?3gs5~X0-QKBhMP8H+?t$R_ySg&{8{_*!s$Tbeq~dv);4(4LUy`KJ>U!obl4L zwOP^e8#m40ebCCGZa`$x&P6H5O3%0<$hS11+cG`b@4>aba9= zs`aRKY46|0T>3Sm&G-b9Vr|1iUMD&?ShRoL?Ou%^boqTu;y>Qa$eToW1@Q%Z=MVE7d&mMofPrlTU%Jzikf}-W)%p?5DANoHoS9lelcVJ;-@qOWU2k(V)pT-?66znnQtV75U%M#XSlr8NqW_100w*01v{ReNI zFrZS`;SPzD#6?VwP3{)&QZaeZf?9oNe|u}P@N3;7K0Vuy{UETz2cg_iLuY&$XZNLP z^tiG|s$OsLwQrFH%UcxkepEE|tb?iP^NKc&w|UiX+O+b;HUsZvg!{VvEH5i+S*_Um z&D}3J8#xRY`hDp_xsT=)oBj5A54$}lD{tKJU}k|ak+0U2x_M(~$?(9a#k2h{Eq<~z z-gWm~`^-Uus#f2dJZ4Zr=(}gNr`YbV@XXpReU8w7_$ZXytdPm`7P}SQmQ8gy;#27N zhC&q+`+eTO+OMhWo5B}+RZQ+wu27AnALGloTv}gbr|i;cKUeRBN>2)Abl==K+S0y3 ze}Nr73FS&JG@BQHX6}e9^A>F|55^%~RCI#X_Yyzn%Mg&WecocHfU`pHNC#Il|bKbLb)H`b>Hy(ZdunJ zpPr8FwI%lMjZKyltF$_QuR?M`$2;vS4UZn%ujf_C0J~fP%#ozsM z+_c!S!>`WX7s&lCl)G~A?4}#n?P%A+bk5oLGnbCqu*}Wu%Cd(0LRu92lD_%WsJ%h$ z2YlPqYQxlm=OTk=zUWb{>aYVNhwa^2Xj|&@ds07cU7Bkre+cE)jQHs@@tj%pv}OaR zpV*vK(6aup@Ap!6oi2M5U2}`~WtSTztoMp^iC*kEVD7z&31UeRr>mQ5`Yk{8dd%vB zH+qj3==)PBw@gou?L8)ZsMK!Q_g5b+?2q4g>^lE&`E`TlG~F=reR^Zd`-L1`R;6D) z5*yboL@WzC7Tv$jNi*lWr>dVD6}`W&g>XLVmr$*NJxiWha+yNheoMVkH}XH&IqupSpZDKy*4oytZy)8zWer!l3iQno z${n}AZHZMac3#?)a4_THT)QLHWBbLrEZ^3-vDIy}#br;r4|`MMQ-4hV z!Vd|1cD-zLY^=$}Wm`WiF&lPMAU9JexAg0!FRxZwHo8ZVdB<9H=>E&%TK5Z%6K0FA z22c3-yFj`6wx2gxO-P#N(j)xPYO~KakG%Z@x>)wKFb_7_TqdE>bK&~@Z=u{i?Tr(B zG8IO$v?aI4TyQSDsa0|52ea>MJ6$@FZ+#id-(Av+E?s%|^wjaEERU}(jBrNYJYyS{$c%KMYNaLMpPGiX1||8IY^hlKt#SGqR_ z4(4aSuNYm?l>N?JG`-LJ%d^1$%NC$=uL_D}Ni2cQYlTJJ@6@S+f>rd=R~BZixo3e4 z{73SXQk6nJSStDgc|{=4081YEUs!Lv*|I_0jyQn1*N}1+r#r5O=>3aX))Q@Z+vlEHT&?mxw`9~I@;ZTOXNQ5pm z`v0a*|3((2BU~v}t7TH9l@t5j;{S1-gy|strn#`+G>`U^%b1<%-OENIQ5o1z^G?X~ zKYdU7{in1Wq)V_$s`A6t+3mlt?flz3;Pg|3If6kmHqgaO;i4p=a-vav3(cj;p>VZP zw`h!!-i-ZLYBarz2$ahLqJmXDn{#Ceuk!x#Ebzb50$iODv+D4`i!0;*D--e$mHz*5 z8u1@mC@*-P1@bJAXMsEmNfjkT3Ss>2>c^1gCK%NEiERbh` zJPYJmAkPAM7Ra+eo(1wOkY|BB3*=cK&jNWC$g@D61@bJAXMsEmNfjkT3Ss>2>|Kk=&%sNGe`xK&Z6P41>N*1P4OXPAZxxz0bKqi-3byZ5GZq@8; zs;Oi{rHX)t)f}oxh76GZPw zk8*rCI^&1r6#}9F3QrawGNoh&K!0=w4u!)x5TaQC{TU$;g)0iop%?fw#tTYAF(3{g z8Qj@b>>C=+d+si-ty4&eJy`UX-|7AOal2Pyy+ zfl5GSfbtNZ&Wox6)d5R@?5#wcbY3g{#tr>$44pgo729*WM z`)R-p;3lvS*bf{44gz#e|6$+=kO&+Fl7M5tao_}S5*P!F1wsHh&=hb3+<|65bD#x4 zzmew!&{@g7fj&TAfX-^9bJOVTseynG&>3hA(C?4ZnO`12bAZYcl^rT8^jif~R(}KM zfb+mOAO@HKOac@Debep_3;_B862KSe4-5p_0d0V`fCtbTXa%$cIwB7GEjKzZIS}vz z`~fKt0MNPRT>v_F-W;HF`>1ZwdHf}TQh*sy9IycB_x$L$4T}JmApZie23QNk0+WHE zzz`r37z_*p!ht}*2ap2YfWCky;01I9f+3U66}1N(04IRXVXF*O1nK}{fa)#%?#FuY zYyj2)(*dgMGXbjKvw=B4G%yHI0xF<0&;#fWRDq1DKsBH`Pz#91`;EYAU=^?kSOF{r zMgnS}3(yPb16YD*F|H9nZ(s?K3fKcRfnY!egaSnoHVW4YxYF+`56AsNAP!gn%mwBF z^Z93@(feq=9qB~I$Dg70gxUovSHFOK0C5=u)S{cMYS4s!jm~8D0P<~GWDE&o%!ayOw6vz)yoYZbnd~{D&dQVq^ChnZ^Qk)c5 z2+$57d)fj*`Ni-|vM9X`fck(LPzops6bDKG^?+ z30LCp3{V@>9q0#i1^NPAfL;K-r+3}>YfoHz0KEaK3%-D+jp~nkk|6;G0#d*qkO4tJ z01yZS19E`!kje-B6~Mhd33ffV2e@EuqU ztOCdmuYkt@(Qg4afh)je;1aME*aB<+b&AfA(eM#l-bj}bhRj%WF2;!g(J0ylu`z%}41 za2L1(+y)*24}g2Xec&NL_9k1t0G_$%C`kDXJ$2p9P8PFX&s zt=509Kw-ePtX6cx1~F3Kl1BXjwxfYBlXHDxJ^0FEIsi3i3qL!-ETzg;v%5Bf| zEg?6P@*5jjK}r?8k>FYg*Hy)0mRBhJ;jXcfjg^g+qaEt9txK3RQZ4fCc-wuTTf5@M zM*Zy^tn938S&vy9JY_O1J&tU>8VicEm7Tqn9cxd8x|u^aM1ViCUTN?YjZaQ?&9^uR zJT_Lg4pugzaY%L7P22j8T<%Os8Z{V~$ zzP(8mo&v4+f>H@Q)ysd~Q14nViI(RYDCI#pvpi{`wW;4rE#)mJWSufMZ$#{CGPk;x zVrLSR0U;h z8_#0rmU$*=DdC`y2AfBvwBI_V*Dx(51{CCYbnE5PtDkHlB8`oB6Nr|9QVx`tozgn= zRu)ugdG_!Wk0L#dEEAt!&{8h((pK-P`~9Kg!a|Hl-Z(? z5M{U@a?eS2*r~>{+a16|Ma0%#Bv<%LR6%Gp9uIE1q*2Ffpg36BqA1uJn{cJ7s`2Cg zK51#;px81dQ4vt6gv|J|X8HcgCSyRcx1yqxbzX`^yJy{t&8qnX6lW_ZD%Td^DF&Vm zZylO8J5-GF)P{ImM3$hG0;PNG%J(T3pUZfPt&_+e6tYh9xXb=)FK%5!c0;*FI=n!k zoZB^H%5+D!k1fGNBwGiOFDO)Yt_{k!=h&2FP>A3Hp1~MB`zq9;`@ejS%ROjugXl~@zlw#4v1Faok1>NNu8gTwd_WGldrn4?Eo^ffgO8;LN;iGQ3a%tCc{npEowS- zO&E)ZNgD|YmFo+si7k#So6vxyp(S_1NS)W9_Rcr)Ce2=ZGKwS11w@0!Mf7$_A@h3D zX&1H9Xd+7~g(ubdhG*<#~a0W+91v`O$zWlAxnNp<|h z-E(u_QU8N>k0?6}a5k`YUtMeX*isc3#g5W*5R@X&`r^|=;R|9vKLmwR3hTHRWPX11 z6#qHf58gS$QEaFc^X4f>8ZNrixLY|cJ$7X40ickyrQ;8@T%S>VEuBq$FXG=Pg4Vw3X7{sbtFoOOf_K6*1mgmUNbvlZ8}ct z2Z}A)cv#dLrYQ}c3q?Cz>z(kf9<{x;tiArz)|!@l0(jv4Mo%bEZ)t~BJJvC2tR!9q zg*=DGRonI-I?L0GQP6SHsj(3%90MgPQPZQV``m_o8HI|qs35u+O6it+2i{ayHKcMt z>49#4+Il3F9Z37r1|xYJNW!8*C2GH*ZxP?eb$dN40X+utfYU(YkJ1=!S#^H-%9fp{ zFbcE5pCx1@UqWgib0~jWmDsjUJuP`Mc=(d|XPslZLF)jObg(o`t=c04^`6DUY@j(;xUTJ*OBG*6d}S1r zQjFMPG|Gil!Gj~BGW%2p1-7BAYXb_E__5ohm+Ck2-p5OG#>gBL^7(!xI)6VW_3_un z6C_b7hJ;}p<36R(B+p05Od2ayQ_Q&jdr{ok3WGxT7GXTB>?p$g(C%S8wXH?mf=EeW zMqw?5EGz&M{6T7qH4T$qKTc-tHEe)#Eei{hDrIU_sfDk~mV0+wZzWd3e>-9f9{VZ5f4mNzq#cdb!^EK1fvxxNSrwG@dJ zYMCAwFz^v5e681EQResBuyP$PQK?j>Ge-C=a79X4+l#EoU4xs5hjJmNWM8>_oY7+N z@b$DB99Yue{qYgui*KI43JRYdsz18p(UCuVrOQ2kdccJy&wFY7tk-2MuEZc77i18$ zUJ44ey%}<&ZQ+)!?tsF#RYyS~yM6mHEGVhx9C+UGctaldWn3w@D_f@2NGxPYwS?*^ zvhO`8RI~hh9ZOnTVtIaJqq}%xfj61BQcAmBeN%I&q9lG64jQmrs92uU&9?A|*Y#VQ z=QB1cfHx>m(Z0Bn-8xz)tt@}`m^pa(mRyI{@D3M~+rD!XQp&g2=XlED&az|1nOA3k z!q==JK{CG})bjJ8v0qntr?=KxCtRWq5{F2muBeV=Uhmw5My`B4?TiTyYLS{*JY3*< zq~Hji2O6vch01l|)E<@Hmrwn{cvvpTRMJRlV%In9ai@#ftD9P$Au6twDUh$-h`q5* z$QMINM0NOM)6`kWSwM3^RB(_eJa4ljWD*I?y(uu zP3NfXKc1o*ES0Na(%17+0$r!gD_7F!lqH*CkFH#UtK*`8!^hvw7<7->n)POOprFu4 ze=j8s$#l372MU})DmxuOp`3H;Z+!6DyMp9-qyCZ?pgAA<_SfnD`VwEw`$g761j~A}aA}P$+*YeTy!#>&T|jpztk) zpIjA5C85iMK2Q4GkEY(4d@=AyRiR>O*kIAYj1?yeNOy4k9P^%}Ds)=lnPs|YT)E^l z1=E1}Vq*{wwWDWVeR-HZbp_YUFh4$)*Lpx;r4cWNEZqtozNJ{o^UT}rwW^@=aq>{W zfr@Gy4+^zA2V$dc|47?Wmc_$7hktBQC#+yV+8?<9D>(jP>ynuDaIwPBQ6#RzwQq|o z_PnYPb1;O{jq;}zC}>Kfqdp|uy6b*$Bu}w(5N+al2DbAnVmYZB^(A}_&P@XcQIEP@ z*-6Q~u%)g;u>~xp%+|T_*yz!~x*m6qv-8m@yXUn`xddr^kI@_yDk1J`Q-9f23H!|J zhPKxWlv1D+vvO#W^0}1{&x0{~E<9)xpYS|N&wXhPZ;3ZDtyvBJ1Pb+Cz1F`z)oR80 zAuJwN4*p@g!)DC>=UWO}F*m>5e?`OBEAPJRmygX`!fYaMP-qTC9dX#@c>R$zwGC@9rHxv(jJ z`G)t4e9}@g>JvzwYZkj z92AP@!I1-%woN$NR!gal948;9?=K%Uxgqg^LZsMd$?85{aGHI+tS@Dm$h zkkJB^VxTk+k{7#FBl#)gv9(8M?+pss?cvnZJrXnb(`XkZhiaqd6!O6FMIU@Eu)IA< zqn^o5G*saai({?Q>B;LhtwtRM1+5OMu%15aE8?MA-_YGpQYuYKz6*3CC&|p7E2F#o zuddioz7lyT96_WzJ=Bm&B4rBdI9;}7%s6!>j@l}I#P28ZW4fgsG|h~7Rl*GvC#+*& z9#(UDv-n}T^m{jq#)0AhiZj+bA~Yux*5h z#%t2kvi02(P2ZA5F@282ie`fX_doi;quPfLoqSkPE3G3c5tW@XrJuL2JFzY0DR`XF z#LfYQa<0~iwO#5|49>?<95I!(6%=&3(a$>#HR;eTZjY9tR$*ovDQ&&%e*DU^2fnd* z(DwZ~7Yz#K0wirl-$1tB^}WiS8PQAka?)TRyS+TcwcYe+(UVy>K|!G=X~#e*1fHX2 zjXw`)Ka0F4ehyM8mH4Tl!HgHT9+aPPd=7a+w#aL&>LTOFb8wT_upd$H##f>^SlJ`* z{H4ATfd~;hR^*UU;p|DK8}s9XRoqG9u1eqjP0MYh5<ZY7@UZcPT%DG26q0rl6zYFG6MjE> z(DzX{E#)RCX2kPy;leJ~$EZD^N`hR_>2WciJQY0DzV#Zq`p{>K2V1n#3c7IKn#1sE z3(|-0c)(Fe>)b7>V|+@ZL)cn#lD}fXr4l12wx17aSX86}7l(LA>ywpAXD&%CQBI?Q zqi7>2v{w0gqjb&EE6a9kH8{|Ss|)tC{DvM~vK$`%7QCUHJB6z`@idl5&e(ONQ2}|7 z&i10ae26{ePTWgQ&ZHKWtYh0K>lXz&y<4%a_vzu>+#v7S`AOswf9Wszv5XFVA_ss6 z?I>Bavn$sgs3x_|+_k3Wa2Aiwl$JE=i?CD&qOeyJQ(U6-`P*((7+#&`RLQeLyPJDC z*xQ8b0sG&6Z`E;mg-PJy%TDffJ7+z`xP%{P=`Pp$OQOy?$JHOqt4ri6k=5b7RxRx6 zULhO61Tc^8c&M$?-SQD7_ga!$U2x2`F4&27H05mma{c5IH*T2H=$-fMbmknZCAnKv z^E(Q!JA1mle%kr9Hs}6LO8>d9?3jy1Dd%)slqkAe3ZjInsGY_BlwHTKC)}Lg7U@Cj zO08vX>CxAUX?~r-;YZO!J?3ujua%a|tS&|cO`3E0)9>aT#o|^*QH+Pp(0YJEJ?+ys z`zs_?%eV{*c~59VhA5Q&G}qUqaB0VOrSAuTLSsPGMsHqP#T!FydPF%i%ttkg&6I3u z!NoH@u1!#S#dvG*@a13+DAZoZ?l1OY;i~1Om^9XxoB)N|-inqc%Y2qQVBUrNDo1!} z66!BPWa^8XrFN^thpD~BTq|j?xFy%ddk?9<%<=NpOvb}jY&L>I>9IDNJ-`1s$tO_A z*0y$-8w{0-{e4BpPOScragx@}&{VP3MbV1W%{+2s#hS|>VFqv{pVFLuRY@Z|4=!v@ zZv(a7-inP_#~}puKW$3wtG0A&aq=l>wGUoRfJ%(59!g2S5%G?_Mi#Xst;ylB!7qm> z!e~pm*Rl22T^kq6(3q(Do46;3g>Kq5Qh(Y3$MU;zUrW zh1E;RDGfPC<862icUp7t%(U)3t#(4wM#e_^3Yw@vTWjWLHpV-3+xv5f`@ESaLDJ&F%x{r z_vdrY0Tk+?u1$YZaKYM8dalP#$V2OFpq?l53*=FuUq-kGYj31*+wHu zD)G>b*4o7QiKb?j$s@-Y6F^;{UUZj40HNTO?p@2!Kx-{l?Uxtt5i}Y ze#xxg)oPkccoW z%Y|8^@enIiDtw1RYf$Q_aQxhmQWmam#%`^BBf`SMLtUE%tCZG3Ap-_zgNpI%O<1IC z78GLr=gW`~RgkqLTn35ZDpzZ3r8E$3lQPN*!h%&+3T2=*ze&wnthp0&d(^DdfkT`5 zN_?eqYh^^38V#%-A=v{$7SAGP<0>1Hg{Y-rQl&(#P>Kx;)DfDb{wYI@LPFIDG3e7z zV+aU=Ilx3a^jH!Fc>v>TtjT_wO^jtS6@_mmc!arykKyu&Kv|gBUn&h3%Vl99x@as)i#I0^`WCy=PiR{`operIv<@vCgX?8rPeMeWhv%8X!G|hhKz8 z(c$mJtRLbz4HdoYnq^l3BK48Q)S|l>D%zX`O;P0wIE~m@wfjfuf(J%5Lw{Y$t}$&X zV5a^fEm;(n3{=v8AXbpGIpqpSOt2%#73O6lJxSKsDyuwYNvBqUFJovO-~c$2+-zw@ z%@6lgNR6o6x66R{Ks0WIc!-FoVew{*);}x_7`HdoMS)++ieF{c14kaFJf zDDZGMVs0!>Ow1)@O|()ei4sSIp;^_VzeF1f(gaUT4?{IAD>CqA-6PHP54tp?MiX<7 z)&VLjn&%Tf50S`2NKNFl65c_m%ulIcyQ%ajs|`ff%Hlww@lrr4Ra$6d~#@(R07l`{}`&aw*$DAiPok#GzGh+P;)<%bqcrqA*^ zLUTfSR;CtfYvGMjHNljkRIVp^!eEdjd}KPZ+RQa?tn#QOst`Tma)gA$9B-IVLoHRd zRH6;wlZZQ{4?eB|vs0@wh z|Acx$J?6>^0|{C8tZ6c&Ft^tkY}^g10!=*YS64+lr@_Lmf7Q!mb+X{fx))P#Zb(1P z-g08(x0xeGnj+%b7@MQ(~@IUiX4OKgS$1mexdw;=26E0M;!Z4ho z^;KF7UmESfDKK>37V@{g5P!RA^rH~KSSKs*%OaKc@%^{pOO|8IB z*-OQt3jYYXlr;xzGE5Z_9*$wNN{nZ;!dBLzk+RF1j*V5R7^~v8K}p@hb1c7UsLp3SZo$XF1F^v(Qd3kOjwyqJBRKo-C{0TxWeLuCHyAX!BI9!6NIKLh3O^RygRNb*~*?lPY4BI!Z3p zCq%0kq-Y7!Vg0sgyqHD!&DS@Wo!HImW}P?by)#!8%?^k)wUdD&mU*)Y5= zAt**9KwIiDoThaR{dUZ~P|^6qP*<0;Q-cCIU!h`X3a1h)u3}ZVWC)s>K&&ytdDA3OJ<~iU)Brt1knIp||jV%$fkC?33%82$^Pcm6}h+|ilBtzwgeZB+^cGVg| zPaN!c4{)$6=S~}JCdgkIqN0X@pK=^PVp?jXwNpLu3a1nJ714-r zT2+PYY|luA;gYXI8ZuNa*9v2gOqQYcNQW#1rI^=Bq58K{gsa(FdBV5B#{bVlF2>6_fbkw z@94V&9Q}&=hOrEm0{k#H7Agsp`N4T4&upkH6w5FHO8t(5AQVz0cw(-Dp@v5oAJ~PD zWNZvB3{4T~u?|@{yS<>3;koIYHi4L&ul~wU6xtawgpZ8h(6nr}%!L3hm)YRe&@=%1 zaFDUkc!NARLm9z;gvfZ<=ZN4k?03*djbNb*Y8SugsHfy-FNomG{^GAZ0&TG-{;V?o zS4$i@s|ZQJ1Y?+>)-Y>vi{&(F%gFjtMC@5&(6t$!KhasqAtI~7!<4+UB`n<7Nk)@h zIa>s5zs0-_Ptc>NP*gS^#GLJ!YvkB;xsZpSo2IRye;JE_gQbp}(WZ@Ev?yVyKnmj) zBps3jPfS;ComALJO4VYv?cgsJRcXRQc-B2D|I7!YV!-dK)H^Ka!Y~=37`eegr4NPl zJMP*oVBpg}z(V|b9o!)a*<6eTdCpy88^*-Gm{Eq49?Iz93V9SQ|LaNbA7K&SAMa5A z(Bc|$bhHYP4BEcNw1Lk2Fo&hXUlA&e^pl3u1p5%FFZC%>Nhnq+4C|^ZIHJ<^ni=Y^ zj4aegV{73%}VkCxnuCa&)rblhou2SV>KOqx1r?gaFF;diikYR zXGSVeX8&f-iVk^fE2LH$d;BYRONT6eBc@gw|Ki`uqlsL>-cqgH9E5)>KWi7PR&v&> ze=HNzkr0Fb87CW22~9+VA+j)gJ8`6wgE&+*7#^T@t1MA*UK;`sIVS~6f)SC7FEA`3 zCy{59C_{5&WF)Z;R!%NQ4vkRBbBfNQ6SGv}D+>zH9fT!GhX5|YG6_+kl64Oo*G-uew$!(BthR@S*A^@hil~P5x zG>rC;FxNx#pdI##F@X~;z*5NUo3U@pRJN@LC*3>40C6JH8UaVHp zh7XAveYU=>xZL3a(2cu6X7S5){I@Hd0#eMoiTTkb*6iW8(_SY%*3!*@Xmk@;w9HH4 zCNbFuHhkjs@AA&3CggMa!n3A>3z%8Ck9C-F^eD{BVZk7VUH_EA6&!x{Lz6jN1U!kK zpv3A7G85ki1<3Sngyo~v!whBgP)S96Z)?Dj%pMCjcf)J16`$?(-^taMFfv(Ial=5H z->0X?;B*oOapA&hw!z)!>_74;Xu$_Zet?gkI_6DFtqu%8l^36eu@BYI`sm$~Kt+s&p)_gk(YU}6hFp9>Ow1rz z@nR{+u;m3RgPSzx3OXCr3BTL0%T{hw{1ZMF3a8`WHIGUOhO#QnW7gMfS+UR;Of*Bt zuU6s{CYqq6`G{=d`CV&bG;Luj8h2{q<4Zr*Zo*}Vmv&>R@tG>*3Nl7p;RADbHQ7 zpyK-~6+^IR4u_ej)LBUiMY{?=S}n;QjkfM9*r4{W^~=eqRW2vx@9O2Bin5H(Qd^Kd zJvs`L4u0VyhN9>LnX|wOjJ=JGjjfZ53$~xjB2?_d7pYW^`D7*KmIAZK*rOwh2xa4b zB`6Y=6gvlLL@CZD*I(aGdfg0AO*eu1R<3KMFD}^fwaTq&HK>k(yq}jRV}0~b6zQ@zsi7kqkQ7HN7eli+!pwvq;Ufgl z+&g7@BSX`4S=)#pBkP{6p&K$Lf1C;U_&aJH4K|KBC)wCpJO*r+y&iM>X9X=0G~gSH zKS+Y6Q>PGFDBF6gC+qdG{Sh%Q?jJP+Xi-@U4PlzwziR-pnh{MC4hd{m4QtOi87%kl z4Zm6uf(`I`l9?3-LbC4JG?<}s$g7dnvp_)By&xep3CoUA(W?Y%B~t)bR+|1Ya!scP zUd`>_dBt zTm>N=_&Y9Z3~?hT>BtkX@pr6gvEjZVHq^ARGr7RZuFNMhlyJfD2z-L4zbXuL4h`7o zg4pPDHT_MpX1u2vRb+b>;}i!zr>N*^$8&nhuQm|W&_1AiICCF^g-I1+c7}}B%Zdn; z<6L@dm8Dp?2fd3FS>X{y);*c0k-=i6IX?%Snp-YA4cJMmEI73f7#A4cyPuU}ux8yO zclggL^cWL+Xu*U3u^|lKLmHa;U z%jo#73x1HkmN92g#F6tAqQmh(hCG1m8bD0;7bL`BkqZ?xOr%xmJ!;Fv$I>N|6iOQiT*mJyr82OM&UXU0<`$*gaN{nV-C~Kspbg7#G~7cIgfpTd+4d4jls?y1 z*F+M;Y37vJK%6Ck-&vp`=&_0>h)@hP<4al~tvzE;t~fx2kHX0f!3M4XeH-9~!5~xk zh!Vq3PU+D{5F^+HPbkDFafWiH9?Y|00*gMwN4a397_cQl>7WP+ev3qF zHI2uv1O+__*S~O6b$aqnM`%Q<<1MRFhLWsHABfZS`mapDl8YS+kfFJSfAM#pWphUg zF*9k{wT5F(oFNx5M=637lqEQ;hP`HeWfNj@lvb7`L#E9pGDlS)&G>~3zH+cG(@+`vWvIK#1M8O@;Msm4f8awk%|8y;XFdP%af};U9 z?7wIZfCHQ6_OH4Pjip($%8nS*tP(*|?nLyMX!#5|F&cih9wm^+ZH<8d9K%hv(Pv>@ zYhDl~TmobMGS_|QdLWu63VewK^DC`n3hR;9wzk%}AE9QQ)wFAPv2z`>q1ld0)43$~ zr+V~zq6X5*jg@e)8@Ta58Wj9vUJgAO>h-e1@Z2msli|SH1-_sT(bsckg@FvV86CTC N88bVb?mzIq{{!Ly*#rOp literal 0 HcmV?d00001 diff --git a/ossinsight-logo copy.svg b/ossinsight-logo copy.svg new file mode 100644 index 0000000..5339789 --- /dev/null +++ b/ossinsight-logo copy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ossinsight-logo.svg b/ossinsight-logo.svg new file mode 100644 index 0000000..5339789 --- /dev/null +++ b/ossinsight-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..782ff58 --- /dev/null +++ b/package.json @@ -0,0 +1,56 @@ +{ + "$schema": "https://schema.kunkun.sh", + "name": "@huakunshen/ext-ossinsight", + "version": "0.0.1", + "type": "module", + "kunkun": { + "name": "OSSInsight", + "shortDescription": "OSSInsight", + "longDescription": "OSSInsight", + "identifier": "ossinsight", + "permissions": [ + "fetch:all", + "clipboard:read-all", + { + "permission": "open:url", + "allow": [ + { + "url": "https://github.com/**" + } + ] + } + ], + "demoImages": [], + "icon": { + "type": "svg", + "value": "" + }, + "customUiCmds": [], + "templateUiCmds": [ + { + "name": "OSSInsight Trending Repos", + "main": "dist/index.js", + "cmds": [] + } + ] + }, + "scripts": { + "dev": "bun build.ts dev", + "build": "bun build.ts" + }, + "dependencies": { + "@hk/ossinsight-client": "npm:@jsr/hk__ossinsight-client", + "@kksh/api": "0.0.52", + "i18next": "^24.2.1" + }, + "devDependencies": { + "@types/bun": "latest" + }, + "peerDependencies": { + "typescript": "^5.7.3" + }, + "files": [ + "./dist", + ".gitignore" + ] +} diff --git a/src/i18n/en.ts b/src/i18n/en.ts new file mode 100644 index 0000000..331e9f1 --- /dev/null +++ b/src/i18n/en.ts @@ -0,0 +1,5 @@ +const en = { + welcome: "Welcome to Kunkun" +} +export default en +export type Translation = typeof en diff --git a/src/i18n/index.ts b/src/i18n/index.ts new file mode 100644 index 0000000..2f0e1c8 --- /dev/null +++ b/src/i18n/index.ts @@ -0,0 +1,20 @@ +import i18next from "i18next" +import en, { type Translation } from "./en" +import zh from "./zh" + +export function setupI18n(language: "en" | "zh" = "en") { + i18next.init({ + resources: { + en: { + translation: en + }, + zh: { + translation: zh + } + }, + lng: language, // default language + fallbackLng: "en" + }) +} + +export const t = (key: keyof Translation, options?: any) => i18next.t(key, options) diff --git a/src/i18n/zh.ts b/src/i18n/zh.ts new file mode 100644 index 0000000..dc3ab95 --- /dev/null +++ b/src/i18n/zh.ts @@ -0,0 +1,5 @@ +import type { Translation } from "./en" + +export default { + welcome: "欢迎来到Kunkun" +} satisfies Translation diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..7bb85e1 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,80 @@ +import { + Action, + app, + expose, + Form, + fs, + Icon, + IconEnum, + List, + open, + path, + shell, + toast, + ui, + WorkerExtension, +} from "@kksh/api/ui/worker"; +import { client, listTrendingRepos } from "@hk/ossinsight-client/heyapi"; +client.setConfig({ + baseUrl: "https://api.ossinsight.io/v1", +}); + +class TrendingRepos extends WorkerExtension { + async onFormSubmit(value: Record): Promise { + console.log("Form submitted", value); + toast.success(`Form submitted: ${JSON.stringify(value)}`); + } + async load() { + const trendingRepos = await listTrendingRepos({ + query: { + // language: "Rust", + }, + }); + console.log(trendingRepos); + + return ui + .setSearchBarPlaceholder("Enter a search term, and press enter to search") + .then(() => { + return ui.render( + new List.List({ + items: trendingRepos.data?.data.rows.map( + (repo) => + new List.Item({ + title: repo.repo_name ?? "N/A", + value: repo.repo_name + ? `https://github.com/${repo.repo_name}` + : "N/A", + subTitle: `Language: ${ + repo.primary_language ?? "N/A" + }; Stars: ${repo.stars ?? "N/A"}`, + }) + ), + }) + ); + }); + } + + async onActionSelected(actionValue: string): Promise { + switch (actionValue) { + case "open": + break; + + default: + break; + } + } + + onSearchTermChange(term: string): Promise { + console.log("Search term changed to:", term); + return Promise.resolve(); + } + + onListItemSelected(value: string): Promise { + if (value.startsWith("https://github.com/")) { + open.url(value); + } + return Promise.resolve(); + } +} + +expose(new TrendingRepos()); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..49ca356 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + // Enable latest features + "lib": [ + "ESNext", + "DOM" + ], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": false, + "verbatimModuleSyntax": true, + "noEmit": true, + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + } +} \ No newline at end of file