diff options
| author | Dawid Rycerz <dawid@rycerz.xyz> | 2026-01-13 17:13:43 +0100 |
|---|---|---|
| committer | Dawid Rycerz <dawid@rycerz.xyz> | 2026-01-13 17:20:15 +0100 |
| commit | 9fe4480c3981c38ae8e24d0495df957039864a5d (patch) | |
| tree | a5f3e4f8c0732c8cd934c28596c6a4d0ab38a4b4 | |
| parent | c0dcecc43e36eeb6b10f662c1be760736cd0dbac (diff) | |
Remove micro and migrate to use only posts
32 files changed, 722 insertions, 359 deletions
diff --git a/package.json b/package.json index 10978a2..df7f25c 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,8 @@ "prettier-plugin-tailwindcss": "^0.6.13", "reading-time": "^1.5.0", "tailwindcss": "4.1.11", - "typescript": "^5.8.3" + "typescript": "^5.8.3", + "wrangler": "^4.59.0" }, "pnpm": { "overrides": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dd1aabb..db2b694 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,9 +44,6 @@ importers: cssnano: specifier: ^7.0.7 version: 7.0.7(postcss@8.5.3) - fast-xml-parser: - specifier: ^5.2.5 - version: 5.2.5 hastscript: specifier: ^9.0.0 version: 9.0.1 @@ -147,6 +144,9 @@ importers: typescript: specifier: ^5.8.3 version: 5.8.3 + wrangler: + specifier: ^4.59.0 + version: 4.59.0 packages: @@ -286,6 +286,53 @@ packages: '@capsizecss/unpack@2.4.0': resolution: {integrity: sha512-GrSU71meACqcmIUxPYOJvGKF0yryjN/L1aCuE9DViCTJI7bfkjgYDPD1zbNDcINJwSSP6UaBZY9GAbYDO7re0Q==} + '@cloudflare/kv-asset-handler@0.4.1': + resolution: {integrity: sha512-Nu8ahitGFFJztxUml9oD/DLb7Z28C8cd8F46IVQ7y5Btz575pvMY8AqZsXkX7Gds29eCKdMgIHjIvzskHgPSFg==} + engines: {node: '>=18.0.0'} + + '@cloudflare/unenv-preset@2.9.0': + resolution: {integrity: sha512-99nEvuOTCGGGRNaIat8UVVXJ27aZK+U09SYDp0kVjQLwC9wyxcrQ28IqLwrQq2DjWLmBI1+UalGJzdPqYgPlRw==} + peerDependencies: + unenv: 2.0.0-rc.24 + workerd: ^1.20251202.0 + peerDependenciesMeta: + workerd: + optional: true + + '@cloudflare/workerd-darwin-64@1.20260111.0': + resolution: {integrity: sha512-UGAjrGLev2/CMLZy7b+v1NIXA4Hupc/QJBFlJwMqldywMcJ/iEqvuUYYuVI2wZXuXeWkgmgFP87oFDQsg78YTQ==} + engines: {node: '>=16'} + cpu: [x64] + os: [darwin] + + '@cloudflare/workerd-darwin-arm64@1.20260111.0': + resolution: {integrity: sha512-YFAZwidLCQVa6rKCCaiWrhA+eh87a7MUhyd9lat3KSbLBAGpYM+ORpyTXpi2Gjm3j6Mp1e/wtzcFTSeMIy2UqA==} + engines: {node: '>=16'} + cpu: [arm64] + os: [darwin] + + '@cloudflare/workerd-linux-64@1.20260111.0': + resolution: {integrity: sha512-zx1GW6FwfOBjCV7QUCRzGRkViUtn3Is/zaaVPmm57xyy9sjtInx6/SdeBr2Y45tx9AnOP1CnaOFFdmH1P7VIEg==} + engines: {node: '>=16'} + cpu: [x64] + os: [linux] + + '@cloudflare/workerd-linux-arm64@1.20260111.0': + resolution: {integrity: sha512-wFVKxNvCyjRaAcgiSnJNJAmIos3p3Vv6Uhf4pFUZ9JIxr69GNlLWlm9SdCPvtwNFAjzSoDaKzDwjj5xqpuCS6Q==} + engines: {node: '>=16'} + cpu: [arm64] + os: [linux] + + '@cloudflare/workerd-windows-64@1.20260111.0': + resolution: {integrity: sha512-zWgd77L7OI1BxgBbG+2gybDahIMgPX5iNo6e3LqcEz1Xm3KfiqgnDyMBcxeQ7xDrj7fHUGAlc//QnKvDchuUoQ==} + engines: {node: '>=16'} + cpu: [x64] + os: [win32] + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + '@ctrl/tinycolor@4.1.0': resolution: {integrity: sha512-WyOx8cJQ+FQus4Mm4uPIZA64gbk3Wxh0so5Lcii0aJifqwoVOlfFtorjLE0Hen4OYyHZMXDWqMmaQemBhgxFRQ==} engines: {node: '>=14'} @@ -320,150 +367,306 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.27.0': + resolution: {integrity: sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.25.5': resolution: {integrity: sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==} engines: {node: '>=18'} cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.27.0': + resolution: {integrity: sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.25.5': resolution: {integrity: sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==} engines: {node: '>=18'} cpu: [arm] os: [android] + '@esbuild/android-arm@0.27.0': + resolution: {integrity: sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.25.5': resolution: {integrity: sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==} engines: {node: '>=18'} cpu: [x64] os: [android] + '@esbuild/android-x64@0.27.0': + resolution: {integrity: sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.25.5': resolution: {integrity: sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.27.0': + resolution: {integrity: sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.25.5': resolution: {integrity: sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.27.0': + resolution: {integrity: sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.25.5': resolution: {integrity: sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.27.0': + resolution: {integrity: sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.25.5': resolution: {integrity: sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.27.0': + resolution: {integrity: sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.25.5': resolution: {integrity: sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==} engines: {node: '>=18'} cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.27.0': + resolution: {integrity: sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.25.5': resolution: {integrity: sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==} engines: {node: '>=18'} cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.27.0': + resolution: {integrity: sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.25.5': resolution: {integrity: sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==} engines: {node: '>=18'} cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.27.0': + resolution: {integrity: sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.25.5': resolution: {integrity: sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.27.0': + resolution: {integrity: sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.25.5': resolution: {integrity: sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.27.0': + resolution: {integrity: sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.25.5': resolution: {integrity: sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.27.0': + resolution: {integrity: sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.25.5': resolution: {integrity: sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.27.0': + resolution: {integrity: sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.25.5': resolution: {integrity: sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==} engines: {node: '>=18'} cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.27.0': + resolution: {integrity: sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.25.5': resolution: {integrity: sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==} engines: {node: '>=18'} cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.27.0': + resolution: {integrity: sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-arm64@0.25.5': resolution: {integrity: sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-arm64@0.27.0': + resolution: {integrity: sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.25.5': resolution: {integrity: sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.27.0': + resolution: {integrity: sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-arm64@0.25.5': resolution: {integrity: sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-arm64@0.27.0': + resolution: {integrity: sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.25.5': resolution: {integrity: sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.27.0': + resolution: {integrity: sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.0': + resolution: {integrity: sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + '@esbuild/sunos-x64@0.25.5': resolution: {integrity: sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.27.0': + resolution: {integrity: sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.25.5': resolution: {integrity: sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==} engines: {node: '>=18'} cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.27.0': + resolution: {integrity: sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.25.5': resolution: {integrity: sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.27.0': + resolution: {integrity: sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.25.5': resolution: {integrity: sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==} engines: {node: '>=18'} cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.27.0': + resolution: {integrity: sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@expressive-code/core@0.41.2': resolution: {integrity: sha512-AJW5Tp9czbLqKMzwudL9Rv4js9afXBxkSGLmCNPq1iRgAYcx9NkTPJiSNCesjKRWoVC328AdSu6fqrD22zDgDg==} @@ -624,6 +827,9 @@ packages: '@jridgewell/trace-mapping@0.3.27': resolution: {integrity: sha512-VO95AxtSFMelbg3ouljAYnfvTEwSWVt/2YLf+U5Ejd8iT5mXE2Sa/1LGyvySMne2CGsepGLI7KpF3EzE3Aq9Mg==} + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@mdx-js/mdx@3.1.0': resolution: {integrity: sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==} @@ -673,6 +879,15 @@ packages: cpu: [x64] os: [win32] + '@poppinss/colors@4.1.6': + resolution: {integrity: sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==} + + '@poppinss/dumper@0.6.5': + resolution: {integrity: sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==} + + '@poppinss/exception@1.2.3': + resolution: {integrity: sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==} + '@resvg/resvg-js-android-arm-eabi@2.6.2': resolution: {integrity: sha512-FrJibrAk6v29eabIPgcTUMPXiEz8ssrAk7TXxsiZzww9UTQ1Z5KAbFJs+Z0Ez+VZTYgnE5IQJqBcoSiMebtPHA==} engines: {node: '>= 10'} @@ -902,6 +1117,13 @@ packages: engines: {node: '>= 8.0.0'} hasBin: true + '@sindresorhus/is@7.2.0': + resolution: {integrity: sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==} + engines: {node: '>=18'} + + '@speed-highlight/core@1.2.14': + resolution: {integrity: sha512-G4ewlBNhUtlLvrJTb88d2mdy2KRijzs4UhnlrOSRT4bmjh/IqNElZa3zkrZ+TC47TwtlDWzVLFADljF1Ijp5hA==} + '@swc/helpers@0.5.17': resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} @@ -1095,6 +1317,15 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + engines: {node: '>=0.4.0'} + + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + engines: {node: '>=0.4.0'} + hasBin: true + acorn@8.14.1: resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} engines: {node: '>=0.4.0'} @@ -1200,6 +1431,9 @@ packages: bcp-47-match@2.0.3: resolution: {integrity: sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==} + blake3-wasm@2.1.5: + resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==} + blob-to-buffer@1.2.9: resolution: {integrity: sha512-BF033y5fN6OCofD3vgHmNtwZWRcq9NLyyxyILx9hfMy1sXYy4ojFl765hJ2lP0YaN2fuxPaLO2Vzzoxy0FLFFA==} @@ -1534,6 +1768,9 @@ packages: resolution: {integrity: sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==} engines: {node: '>=0.12'} + error-stack-parser-es@1.0.5: + resolution: {integrity: sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==} + es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -1564,6 +1801,11 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.27.0: + resolution: {integrity: sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -1602,6 +1844,10 @@ packages: eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + exit-hook@2.2.1: + resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==} + engines: {node: '>=6'} + expressive-code@0.41.2: resolution: {integrity: sha512-aLZiZaqorRtNExtGpUjK9zFH9aTpWeoTXMyLo4b4IcuXfPqtLPPxhRm/QlPb8QqIcMMXnSiGRHSFpQfX0m7HJw==} @@ -1720,6 +1966,9 @@ packages: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + globals@15.15.0: resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} engines: {node: '>=18'} @@ -2224,6 +2473,16 @@ packages: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} + mime@3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true + + miniflare@4.20260111.0: + resolution: {integrity: sha512-pUsbDlumPaTzliA+J9HMAM74nLR8wqpCQNOESximab51jAfvL7ZaP5Npzh4PWNV0Jfq28tlqazakuJcw6w5qlA==} + engines: {node: '>=18.0.0'} + hasBin: true + minipass@3.3.6: resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} engines: {node: '>=8'} @@ -2370,6 +2629,9 @@ packages: path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + path-to-regexp@6.3.0: + resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} + pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} @@ -2863,6 +3125,10 @@ packages: space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + stoppable@1.1.0: + resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} + engines: {node: '>=4', npm: '>=6'} + stream-replace-string@2.0.0: resolution: {integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==} @@ -2906,6 +3172,10 @@ packages: suf-log@2.5.3: resolution: {integrity: sha512-KvC8OPjzdNOe+xQ4XWJV2whQA0aM1kGVczMQ8+dStAO6KfEB140JEVQ9dE76ONZ0/Ylf67ni4tILPJB41U0eow==} + supports-color@10.2.2: + resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} + engines: {node: '>=18'} + svgo@3.3.2: resolution: {integrity: sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==} engines: {node: '>=14.0.0'} @@ -3002,6 +3272,13 @@ packages: resolution: {integrity: sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==} engines: {node: '>=18.17'} + undici@7.14.0: + resolution: {integrity: sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==} + engines: {node: '>=20.18.1'} + + unenv@2.0.0-rc.24: + resolution: {integrity: sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==} + unicode-properties@1.4.1: resolution: {integrity: sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==} @@ -3304,6 +3581,21 @@ packages: resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} engines: {node: '>=18'} + workerd@1.20260111.0: + resolution: {integrity: sha512-ov6Pt4k6d/ALfJja/EIHohT9IrY/f6GAa0arWEPat2qekp78xHbVM7jSxNWAMbaE7ZmnQQIFEGD1ZhAWZmQKIg==} + engines: {node: '>=16'} + hasBin: true + + wrangler@4.59.0: + resolution: {integrity: sha512-YYTYELFHsWfkx4oT+SB6fV8r/4mzR/ySQrcSoGavdHsXNux7ge6UNscMifWnqyyB76meCVTkgsXrRONGoV7bEQ==} + engines: {node: '>=20.0.0'} + hasBin: true + peerDependencies: + '@cloudflare/workers-types': ^4.20260111.0 + peerDependenciesMeta: + '@cloudflare/workers-types': + optional: true + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -3315,6 +3607,18 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + xxhash-wasm@1.1.0: resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==} @@ -3368,6 +3672,12 @@ packages: yoga-wasm-web@0.3.3: resolution: {integrity: sha512-N+d4UJSJbt/R3wqY7Coqs5pcV0aUj2j9IaQ3rNj9bVCLld8tTGKRa2USARjnvZJWVx1NDmQev8EknoczaOQDOA==} + youch-core@0.3.3: + resolution: {integrity: sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==} + + youch@4.1.0-beta.10: + resolution: {integrity: sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==} + zod-to-json-schema@3.24.6: resolution: {integrity: sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==} peerDependencies: @@ -3385,6 +3695,9 @@ packages: zod@3.25.67: resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==} + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -3577,6 +3890,35 @@ snapshots: transitivePeerDependencies: - encoding + '@cloudflare/kv-asset-handler@0.4.1': + dependencies: + mime: 3.0.0 + + '@cloudflare/unenv-preset@2.9.0(unenv@2.0.0-rc.24)(workerd@1.20260111.0)': + dependencies: + unenv: 2.0.0-rc.24 + optionalDependencies: + workerd: 1.20260111.0 + + '@cloudflare/workerd-darwin-64@1.20260111.0': + optional: true + + '@cloudflare/workerd-darwin-arm64@1.20260111.0': + optional: true + + '@cloudflare/workerd-linux-64@1.20260111.0': + optional: true + + '@cloudflare/workerd-linux-arm64@1.20260111.0': + optional: true + + '@cloudflare/workerd-windows-64@1.20260111.0': + optional: true + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + '@ctrl/tinycolor@4.1.0': {} '@emmetio/abbreviation@2.3.3': @@ -3610,78 +3952,156 @@ snapshots: '@esbuild/aix-ppc64@0.25.5': optional: true + '@esbuild/aix-ppc64@0.27.0': + optional: true + '@esbuild/android-arm64@0.25.5': optional: true + '@esbuild/android-arm64@0.27.0': + optional: true + '@esbuild/android-arm@0.25.5': optional: true + '@esbuild/android-arm@0.27.0': + optional: true + '@esbuild/android-x64@0.25.5': optional: true + '@esbuild/android-x64@0.27.0': + optional: true + '@esbuild/darwin-arm64@0.25.5': optional: true + '@esbuild/darwin-arm64@0.27.0': + optional: true + '@esbuild/darwin-x64@0.25.5': optional: true + '@esbuild/darwin-x64@0.27.0': + optional: true + '@esbuild/freebsd-arm64@0.25.5': optional: true + '@esbuild/freebsd-arm64@0.27.0': + optional: true + '@esbuild/freebsd-x64@0.25.5': optional: true + '@esbuild/freebsd-x64@0.27.0': + optional: true + '@esbuild/linux-arm64@0.25.5': optional: true + '@esbuild/linux-arm64@0.27.0': + optional: true + '@esbuild/linux-arm@0.25.5': optional: true + '@esbuild/linux-arm@0.27.0': + optional: true + '@esbuild/linux-ia32@0.25.5': optional: true + '@esbuild/linux-ia32@0.27.0': + optional: true + '@esbuild/linux-loong64@0.25.5': optional: true + '@esbuild/linux-loong64@0.27.0': + optional: true + '@esbuild/linux-mips64el@0.25.5': optional: true + '@esbuild/linux-mips64el@0.27.0': + optional: true + '@esbuild/linux-ppc64@0.25.5': optional: true + '@esbuild/linux-ppc64@0.27.0': + optional: true + '@esbuild/linux-riscv64@0.25.5': optional: true + '@esbuild/linux-riscv64@0.27.0': + optional: true + '@esbuild/linux-s390x@0.25.5': optional: true + '@esbuild/linux-s390x@0.27.0': + optional: true + '@esbuild/linux-x64@0.25.5': optional: true + '@esbuild/linux-x64@0.27.0': + optional: true + '@esbuild/netbsd-arm64@0.25.5': optional: true + '@esbuild/netbsd-arm64@0.27.0': + optional: true + '@esbuild/netbsd-x64@0.25.5': optional: true + '@esbuild/netbsd-x64@0.27.0': + optional: true + '@esbuild/openbsd-arm64@0.25.5': optional: true + '@esbuild/openbsd-arm64@0.27.0': + optional: true + '@esbuild/openbsd-x64@0.25.5': optional: true + '@esbuild/openbsd-x64@0.27.0': + optional: true + + '@esbuild/openharmony-arm64@0.27.0': + optional: true + '@esbuild/sunos-x64@0.25.5': optional: true + '@esbuild/sunos-x64@0.27.0': + optional: true + '@esbuild/win32-arm64@0.25.5': optional: true + '@esbuild/win32-arm64@0.27.0': + optional: true + '@esbuild/win32-ia32@0.25.5': optional: true + '@esbuild/win32-ia32@0.27.0': + optional: true + '@esbuild/win32-x64@0.25.5': optional: true + '@esbuild/win32-x64@0.27.0': + optional: true + '@expressive-code/core@0.41.2': dependencies: '@ctrl/tinycolor': 4.1.0 @@ -3844,6 +4264,11 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.2 + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.2 + '@mdx-js/mdx@3.1.0(acorn@8.14.1)': dependencies: '@types/estree': 1.0.7 @@ -3907,6 +4332,18 @@ snapshots: '@pagefind/windows-x64@1.3.0': optional: true + '@poppinss/colors@4.1.6': + dependencies: + kleur: 4.1.5 + + '@poppinss/dumper@0.6.5': + dependencies: + '@poppinss/colors': 4.1.6 + '@sindresorhus/is': 7.2.0 + supports-color: 10.2.2 + + '@poppinss/exception@1.2.3': {} + '@resvg/resvg-js-android-arm-eabi@2.6.2': optional: true @@ -4095,6 +4532,10 @@ snapshots: fflate: 0.7.4 string.prototype.codepointat: 0.2.1 + '@sindresorhus/is@7.2.0': {} + + '@speed-highlight/core@1.2.14': {} + '@swc/helpers@0.5.17': dependencies: tslib: 2.8.1 @@ -4298,6 +4739,10 @@ snapshots: dependencies: acorn: 8.14.1 + acorn-walk@8.3.2: {} + + acorn@8.14.0: {} + acorn@8.14.1: {} acorn@8.15.0: {} @@ -4495,6 +4940,8 @@ snapshots: bcp-47-match@2.0.3: {} + blake3-wasm@2.1.5: {} + blob-to-buffer@1.2.9: {} boolbase@1.0.0: {} @@ -4838,6 +5285,8 @@ snapshots: entities@6.0.0: {} + error-stack-parser-es@1.0.5: {} + es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -4897,6 +5346,35 @@ snapshots: '@esbuild/win32-ia32': 0.25.5 '@esbuild/win32-x64': 0.25.5 + esbuild@0.27.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.0 + '@esbuild/android-arm': 0.27.0 + '@esbuild/android-arm64': 0.27.0 + '@esbuild/android-x64': 0.27.0 + '@esbuild/darwin-arm64': 0.27.0 + '@esbuild/darwin-x64': 0.27.0 + '@esbuild/freebsd-arm64': 0.27.0 + '@esbuild/freebsd-x64': 0.27.0 + '@esbuild/linux-arm': 0.27.0 + '@esbuild/linux-arm64': 0.27.0 + '@esbuild/linux-ia32': 0.27.0 + '@esbuild/linux-loong64': 0.27.0 + '@esbuild/linux-mips64el': 0.27.0 + '@esbuild/linux-ppc64': 0.27.0 + '@esbuild/linux-riscv64': 0.27.0 + '@esbuild/linux-s390x': 0.27.0 + '@esbuild/linux-x64': 0.27.0 + '@esbuild/netbsd-arm64': 0.27.0 + '@esbuild/netbsd-x64': 0.27.0 + '@esbuild/openbsd-arm64': 0.27.0 + '@esbuild/openbsd-x64': 0.27.0 + '@esbuild/openharmony-arm64': 0.27.0 + '@esbuild/sunos-x64': 0.27.0 + '@esbuild/win32-arm64': 0.27.0 + '@esbuild/win32-ia32': 0.27.0 + '@esbuild/win32-x64': 0.27.0 + escalade@3.2.0: {} escape-html@1.0.3: {} @@ -4940,6 +5418,8 @@ snapshots: eventemitter3@5.0.1: {} + exit-hook@2.2.1: {} + expressive-code@0.41.2: dependencies: '@expressive-code/core': 0.41.2 @@ -5068,6 +5548,8 @@ snapshots: dependencies: is-glob: 4.0.3 + glob-to-regexp@0.4.1: {} + globals@15.15.0: {} gopd@1.2.0: {} @@ -5914,6 +6396,26 @@ snapshots: dependencies: mime-db: 1.52.0 + mime@3.0.0: {} + + miniflare@4.20260111.0: + dependencies: + '@cspotcode/source-map-support': 0.8.1 + acorn: 8.14.0 + acorn-walk: 8.3.2 + exit-hook: 2.2.1 + glob-to-regexp: 0.4.1 + sharp: 0.34.2 + stoppable: 1.1.0 + undici: 7.14.0 + workerd: 1.20260111.0 + ws: 8.18.0 + youch: 4.1.0-beta.10 + zod: 3.25.76 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + minipass@3.3.6: dependencies: yallist: 4.0.0 @@ -6058,6 +6560,8 @@ snapshots: path-browserify@1.0.1: {} + path-to-regexp@6.3.0: {} + pathe@1.1.2: {} pathe@2.0.3: {} @@ -6637,6 +7141,8 @@ snapshots: space-separated-tokens@2.0.2: {} + stoppable@1.1.0: {} + stream-replace-string@2.0.0: {} string-width@4.2.3: @@ -6686,6 +7192,8 @@ snapshots: dependencies: s.color: 0.0.15 + supports-color@10.2.2: {} + svgo@3.3.2: dependencies: '@trysound/sax': 0.2.0 @@ -6771,6 +7279,12 @@ snapshots: undici@6.21.3: {} + undici@7.14.0: {} + + unenv@2.0.0-rc.24: + dependencies: + pathe: 2.0.3 + unicode-properties@1.4.1: dependencies: base64-js: 1.5.1 @@ -7031,6 +7545,30 @@ snapshots: dependencies: string-width: 7.2.0 + workerd@1.20260111.0: + optionalDependencies: + '@cloudflare/workerd-darwin-64': 1.20260111.0 + '@cloudflare/workerd-darwin-arm64': 1.20260111.0 + '@cloudflare/workerd-linux-64': 1.20260111.0 + '@cloudflare/workerd-linux-arm64': 1.20260111.0 + '@cloudflare/workerd-windows-64': 1.20260111.0 + + wrangler@4.59.0: + dependencies: + '@cloudflare/kv-asset-handler': 0.4.1 + '@cloudflare/unenv-preset': 2.9.0(unenv@2.0.0-rc.24)(workerd@1.20260111.0) + blake3-wasm: 2.1.5 + esbuild: 0.27.0 + miniflare: 4.20260111.0 + path-to-regexp: 6.3.0 + unenv: 2.0.0-rc.24 + workerd: 1.20260111.0 + optionalDependencies: + fsevents: 2.3.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -7045,6 +7583,8 @@ snapshots: wrappy@1.0.2: {} + ws@8.18.0: {} + xxhash-wasm@1.1.0: {} y18n@5.0.8: {} @@ -7099,6 +7639,19 @@ snapshots: yoga-wasm-web@0.3.3: {} + youch-core@0.3.3: + dependencies: + '@poppinss/exception': 1.2.3 + error-stack-parser-es: 1.0.5 + + youch@4.1.0-beta.10: + dependencies: + '@poppinss/colors': 4.1.6 + '@poppinss/dumper': 0.6.5 + '@speed-highlight/core': 1.2.14 + cookie: 1.0.2 + youch-core: 0.3.3 + zod-to-json-schema@3.24.6(zod@3.25.67): dependencies: zod: 3.25.67 @@ -7112,4 +7665,6 @@ snapshots: zod@3.25.67: {} + zod@3.25.76: {} + zwitch@2.0.4: {} diff --git a/public/_redirects b/public/_redirects index 2fe6215..f356960 100644 --- a/public/_redirects +++ b/public/_redirects @@ -1,7 +1,8 @@ /contact / 301 -/micro/ /tags/micro/ 301 -/micro/rss.xml /tags/micro/rss.xml 301 -/micro/* /tags/micro/:splat 301 +/micro/ /tags/microblog/ 301 +/micro/rss.xml /tags/microblog/rss.xml 301 +/micro/pleroma-* /posts/pleroma-:splat 301 +/micro/* /tags/microblog/:splat 301 /niedziela-11-wrzesnia-2022/ /posts/niedziela-11-wrzesnia-2022/ 301 /piatek-7-pazdziernika-2022/ /posts/piatek-7-pazdziernika-2022/ 301 /piatek-9-wrzesnia-2022/ /posts/piatek-9-wrzesnia-2022/ 301 diff --git a/src/components/BaseHead.astro b/src/components/BaseHead.astro index 40f1d20..14286c3 100644 --- a/src/components/BaseHead.astro +++ b/src/components/BaseHead.astro @@ -95,7 +95,6 @@ const ogLocale = getOgLocale(lang); {/* RSS auto-discovery */} <link href="/rss.xml" title="Blog" rel="alternate" type="application/rss+xml" /> -<link href="/micro/rss.xml" title="Micro" rel="alternate" type="application/rss+xml" /> {/* Webmentions */} { diff --git a/src/components/note/Note.astro b/src/components/note/Note.astro deleted file mode 100644 index 920cbc1..0000000 --- a/src/components/note/Note.astro +++ /dev/null @@ -1,86 +0,0 @@ ---- -import { type CollectionEntry, render } from "astro:content"; -import type { HTMLTag, Polymorphic } from "astro/types"; -import FormattedDate from "@/components/FormattedDate.astro"; - -type Props<Tag extends HTMLTag> = Polymorphic<{ as: Tag }> & { - note: CollectionEntry<"micro">; - isPreview?: boolean | undefined; -}; - -const { as: Tag = "div", note, isPreview = false } = Astro.props; -const { Content } = await render(note); ---- - -<article - class:list={[ - isPreview && "inline-grid rounded-md bg-[rgb(240,240,240)] px-4 py-3 dark:bg-[rgb(33,35,38)]", - ]} - data-pagefind-body={isPreview ? false : true} -> - <Tag class="title" class:list={{ "text-base": isPreview }}> - { - isPreview ? ( - <a class="cactus-link" href={`/micro/${note.id}/`}> - {note.data.title} - </a> - ) : ( - <>{note.data.title}</> - ) - } - </Tag> - <FormattedDate - dateTimeOptions={{ - hour: "2-digit", - minute: "2-digit", - year: "2-digit", - month: "2-digit", - day: "2-digit", - }} - date={note.data.publishDate} - /> - <div - class="prose prose-sm prose-cactus mt-4 max-w-none [&>p:last-of-type]:mb-0" - class:list={{ "line-clamp-6": isPreview }} - > - <Content /> - { - !isPreview && note.data.attachments && note.data.attachments.length > 0 && ( - <div class="mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2"> - {note.data.attachments.map((attachment: { type: string; url: string; alt?: string }) => ( - <a - href={attachment.url} - target="_blank" - rel="noopener noreferrer" - class="block overflow-hidden rounded-lg border border-gray-200 transition-colors hover:border-gray-300 dark:border-gray-700 dark:hover:border-gray-600" - > - <img - src={attachment.url} - alt={attachment.alt || "Image"} - class="h-48 w-full object-cover" - loading="lazy" - /> - </a> - ))} - </div> - ) - } - { - !isPreview && note.data.sourceUrl && ( - <> - <hr class="mt-6 mb-4 border-t border-gray-300 dark:border-gray-600" /> - <p class="text-sm text-gray-600 dark:text-gray-400"> - <a - href={note.data.sourceUrl} - class="cactus-link" - target="_blank" - rel="noopener noreferrer" - > - View original post → - </a> - </p> - </> - ) - } - </div> -</article> diff --git a/src/content.config.ts b/src/content.config.ts index a9fa0e2..5b5836b 100644 --- a/src/content.config.ts +++ b/src/content.config.ts @@ -35,10 +35,12 @@ const post = defineCollection({ .optional() .transform((str) => (str ? new Date(str) : undefined)), language: z.string().optional(), + sourceUrl: z.string().optional(), + author: z.string().optional(), }), }); -const micro = defineCollection({ +const pleroma = defineCollection({ loader: pleromaLoader({ instanceUrl: "https://social.craftknight.com", username: "dawid", @@ -51,23 +53,8 @@ const micro = defineCollection({ sourceUrl: z.string().optional(), language: z.string().optional(), tags: z.array(z.string()).default([]).transform(removeDupsAndLowerCase), - author: z - .object({ - username: z.string(), - displayName: z.string().optional(), - acct: z.string(), - url: z.string().optional(), - }) - .optional(), - attachments: z - .array( - z.object({ - url: z.string(), - type: z.string(), - alt: z.string().optional(), - }), - ) - .optional(), + draft: z.boolean().default(false), + author: z.string().optional(), }), }); @@ -79,4 +66,4 @@ const tag = defineCollection({ }), }); -export const collections = { post, tag, micro }; +export const collections = { post, tag, pleroma }; diff --git a/src/content/post/devops-mindset.md b/src/content/post/devops-mindset.md index 166d282..7761cc3 100644 --- a/src/content/post/devops-mindset.md +++ b/src/content/post/devops-mindset.md @@ -4,6 +4,7 @@ description: "DevOps - culture, mindset and processes" publishDate: "3 July 2025" tags: ["devops101", devops] draft: false +author: "Dawid" --- ## DevOps Mindset diff --git a/src/content/post/fediverse-101.md b/src/content/post/fediverse-101.md index 6c248b9..595606b 100644 --- a/src/content/post/fediverse-101.md +++ b/src/content/post/fediverse-101.md @@ -4,6 +4,7 @@ description: "A short collection of resources and links for getting started with publishDate: 19 Dec 2025 tags: [fediverse, social] draft: false +author: "Dawid" --- ## Fediverse 101 diff --git a/src/content/post/niedziela-11-wrzesnia-2022.md b/src/content/post/niedziela-11-wrzesnia-2022.md index 6f5a31a..3f47dec 100644 --- a/src/content/post/niedziela-11-wrzesnia-2022.md +++ b/src/content/post/niedziela-11-wrzesnia-2022.md @@ -3,6 +3,7 @@ title: "Niedziela 11 września 2022" description: "Weekend minął jak z bicza strzelił. Zdecydowanie nie był to jeden z tych leniwych weekendów. W sobotę rano poznaliśmy przemiłą starszą parę z Polski." publishDate: "2022-09-11" tags: ["archived"] +author: "Dawid" --- Weekend minął „jak z bicza strzelił". Zdecydowanie nie był to jeden z tych leniwych weekendów. diff --git a/src/content/post/piatek-16-wrzesnia-2022.md b/src/content/post/piatek-16-wrzesnia-2022.md index b6a46a2..104f737 100644 --- a/src/content/post/piatek-16-wrzesnia-2022.md +++ b/src/content/post/piatek-16-wrzesnia-2022.md @@ -3,6 +3,7 @@ title: "Piątek 16 września 2022" description: "Ostatnie dni były wyjątkowo ciepłe. Pogoda sprzyjała plażowaniu, więc po pracy dołączałem do Aleksandry. Mieliśmy swoją miejscówkę koło nadmorskiego baru, który był niestety zamknięty po sezonie." publishDate: "2022-09-16" tags: ["archived"] +author: "Dawid" --- Ostatnie dni były wyjątkowo ciepłe. Pogoda sprzyjała plażowaniu, więc po pracy dołączałem do Aleksandry. Mieliśmy swoją miejscówkę koło nadmorskiego baru, który był niestety zamknięty po sezonie. Rumuńskie plaże całe są w muszelkach. Większe i jeszcze ostre muszle są bliżej wody, natomiast mniejsze kawałki – już pokruszone – tworzą specyficzny "piasek". diff --git a/src/content/post/piatek-7-pazdziernika-2022.md b/src/content/post/piatek-7-pazdziernika-2022.md index 72819db..d278fd3 100644 --- a/src/content/post/piatek-7-pazdziernika-2022.md +++ b/src/content/post/piatek-7-pazdziernika-2022.md @@ -3,6 +3,7 @@ title: "Piątek 7 października 2022" description: "Dotarłem na jedno z najbardziej epickich miejsc, w których zdarzyło nam się spać. Wysokie klify, rozległa polana, ogromne przestrzenie i tylko wypasające się konie, owce i kozy." publishDate: "2022-10-07" tags: ["archived"] +author: "Dawid" --- Dotarłem na jedno z najbardziej epickich miejsc, w których zdarzyło nam się spać. Wysokie klify, rozległa polana, ogromne przestrzenie i tylko wypasające się konie, owce i kozy. Nocą na horyzoncie widać światła Ahtopola, ale poza nimi tylko Księżyc i Jowisz rozświetla okolicę. Nad samą przepaścią ktoś wystawił stolik, krzesło i dalej ławkę, na których co kilka godzin ktoś przyjeżdża zrobić sobie zdjęcia. diff --git a/src/content/post/piatek-9-wrzesnia-2022.md b/src/content/post/piatek-9-wrzesnia-2022.md index 005a673..2ccd517 100644 --- a/src/content/post/piatek-9-wrzesnia-2022.md +++ b/src/content/post/piatek-9-wrzesnia-2022.md @@ -3,6 +3,7 @@ title: "Piątek 9 września 2022" description: "Ostatnie dni miałem bardzo zawalone w pracy. Dużo spotkań, przygotowywania prezentacji, prowadzenie treningów – w sumie poza siedzeniem w laptopie niewiele się wydarzyło." publishDate: "2022-09-09" tags: ["archived"] +author: "Dawid" --- Ostatnie dni miałem bardzo zawalone w pracy. Dużo spotkań, przygotowywania prezentacji, prowadzenie treningów – w sumie poza siedzeniem w laptopie niewiele się wydarzyło. Wiatr za to tak zaczął doskwierać, że musieliśmy zwinąć markizę i prawie całe dwa dni spędziłem w kamperze. Przynajmniej Freja przestała nam plątać się we wsporniki i linki 🙂 diff --git a/src/content/post/poniedzialek-3-pazdziernika-2022.md b/src/content/post/poniedzialek-3-pazdziernika-2022.md index 9ac4688..f4088ed 100644 --- a/src/content/post/poniedzialek-3-pazdziernika-2022.md +++ b/src/content/post/poniedzialek-3-pazdziernika-2022.md @@ -3,6 +3,7 @@ title: "Poniedziałek 3 października 2022" description: "W czwartek rano już się upewniłem, że na skarpie zaparkował Groszek – zielony VW T4 który należy do kampermaniaków. Skończyło mi się wolne, więc szybko tylko poszedłem z Freją po banice do ajranu..." publishDate: "2022-10-03" tags: ["archived"] +author: "Dawid" --- W czwartek rano już się upewniłem, że na skarpie zaparkował Groszek – zielony VW T4 który należy do [kampermaniaków](https://kampermaniak.pl). Skończyło mi się wolne, więc szybko tylko poszedłem z Freją po banice do ajranu, rozłożyłem "biuro" i zacząłem normalny dzień pracy. Jak to ja – nawet na popołudniowym spacerze nie zebrałem się, żeby zagadać, a wieczorem już widziałem, że wszyscy siedzieli i nie chciałem przeszkadzać. diff --git a/src/content/post/poniedzialek-5-wrzesnia-2022.md b/src/content/post/poniedzialek-5-wrzesnia-2022.md index d3456c0..369f091 100644 --- a/src/content/post/poniedzialek-5-wrzesnia-2022.md +++ b/src/content/post/poniedzialek-5-wrzesnia-2022.md @@ -3,6 +3,7 @@ title: "Poniedziałek 5 września 2022" description: "Postanowiliśmy zostać tutaj na dłużej. Miejsce do którego dojechaliśmy okazało się być plażą pełną przyczep kempingowych i kamperów. Mamy widok z okna na morze, szybki internet, dużo słońca (prądu) oraz proste podłoże." publishDate: "2022-09-05" tags: ["archived"] +author: "Dawid" --- Postanowiliśmy zostać tutaj na dłużej. Miejsce do którego dojechaliśmy okazało się być plażą pełną przyczep kempingowych i kamperów. Mamy widok z okna na morze, szybki internet, dużo słońca (prądu) oraz proste podłoże. Chyba gdzieś w okolicy jest źródło wody (przynajmniej na to wygląda sądząc po ludziach noszących butelki). diff --git a/src/content/post/sobota-3-wrzesnia-2022.md b/src/content/post/sobota-3-wrzesnia-2022.md index a77cdb4..0aeb464 100644 --- a/src/content/post/sobota-3-wrzesnia-2022.md +++ b/src/content/post/sobota-3-wrzesnia-2022.md @@ -3,6 +3,7 @@ title: "Sobota 3 września 2022" description: "Dzień wyjazdu z Bukaresztu i ogarniania auta po tygodniu w wynajętym mieszkaniu. Wodę pozwolili nam nalać na stacji po tankowaniu auta, kasete zlaliśmy na parkingu dla kamperów, a po drodze kupiliśmy jeszcze karmę dla Freji." publishDate: "2022-09-03" tags: ["archived"] +author: "Dawid" --- Dzień wyjazdu z Bukaresztu i ogarniania auta po tygodniu w wynajętym mieszkaniu. Wodę pozwolili nam nalać na stacji po tankowaniu auta, kasete zlaliśmy na parkingu dla kamperów, a po drodze kupiliśmy jeszcze karmę dla Freji. diff --git a/src/content/post/sroda-21-wrzesnia-2022.md b/src/content/post/sroda-21-wrzesnia-2022.md index ae2665a..1ff94b5 100644 --- a/src/content/post/sroda-21-wrzesnia-2022.md +++ b/src/content/post/sroda-21-wrzesnia-2022.md @@ -3,6 +3,7 @@ title: "Środa 21 września 2022" description: "W pierwszych dniach pobytu w Bułgarii mieliśmy nieco szczęścia. Warna przywitała nas burzą i oberwaniem chmury. W trakcie spaceru po mieście zerwał się deszcz i przemokliśmy do suchej nitki w przeciągu kilku minut." publishDate: "2022-09-21" tags: ["archived"] +author: "Dawid" --- W pierwszych dniach pobytu w Bułgarii mieliśmy nieco szczęścia. Warna przywitała nas burzą i oberwaniem chmury. W trakcie spaceru po mieście zerwał się deszcz i przemokliśmy do suchej nitki w przeciągu kilku minut. W tym samym czasie, kilkadziesiąt kilometrów na południe, przez Brugas przeszedł huragan który zrywał dachy i łamał drzewa. Dobrze, że zamarudziliśmy trochę i zwiedziliśmy jeszcze po drodze kamienny las. diff --git a/src/content/post/sroda-28-wrzesnia-2022.md b/src/content/post/sroda-28-wrzesnia-2022.md index 884ec2f..e0a456b 100644 --- a/src/content/post/sroda-28-wrzesnia-2022.md +++ b/src/content/post/sroda-28-wrzesnia-2022.md @@ -3,6 +3,7 @@ title: "Środa 28 września 2022" description: "Wziąłem parę dni wolnego, abyśmy mogli spokojnie pozwiedzać okolicę. Zaczęliśmy od oddania rzeczy do pralni. Niestety w Bułgarii pralki na monety nie są popularne." publishDate: "2022-09-28" tags: ["archived"] +author: "Dawid" --- ## Nesebar diff --git a/src/content/post/sroda-7-wrzesnia-2022.md b/src/content/post/sroda-7-wrzesnia-2022.md index 2b70da1..50b2e13 100644 --- a/src/content/post/sroda-7-wrzesnia-2022.md +++ b/src/content/post/sroda-7-wrzesnia-2022.md @@ -3,6 +3,7 @@ title: "Środa 7 września 2022" description: "Musieliśmy się dzisiaj ruszyć po wodę. Źródełko płynące z rury koło domku rybaka okazało się na tyle brudne, że nie ryzykowaliśmy zalewać nim zbiornika w kamperze." publishDate: "2022-09-07" tags: ["archived"] +author: "Dawid" --- Musieliśmy się dzisiaj ruszyć po wodę. Źródełko płynące z rury koło domku rybaka okazało się na tyle brudne, że nie ryzykowaliśmy zalewać nim zbiornika w kamperze. Może i dało by się w nim wykąpać, ale bez wstępnej filtracji tylko by zasyfiło pompę, przewody i krany. Przy okazji zrobiliśmy zakupy w lokalnym Lidlu i umyliśmy auto (było całe od błota po sobotnich "przygodach"). diff --git a/src/content/post/wtorek-13-wrzesnia-2022.md b/src/content/post/wtorek-13-wrzesnia-2022.md index 4023696..09dacc1 100644 --- a/src/content/post/wtorek-13-wrzesnia-2022.md +++ b/src/content/post/wtorek-13-wrzesnia-2022.md @@ -3,6 +3,7 @@ title: "Wtorek 13 września 2022" description: "Przez jeden dzień mieliśmy nowe zwierzątko – konkretnie nietoperza. W poniedziałek nad ranem coś wpadło pomiędzy moskitierę, a okno dachowe i strasznie hałasowało." publishDate: "2022-09-13" tags: ["archived"] +author: "Dawid" --- Przez jeden dzień mieliśmy nowe zwierzątko – konkretnie nietoperza. W poniedziałek nad ranem coś wpadło pomiędzy moskitierę, a okno dachowe i strasznie hałasowało. Na początku myśleliśmy, że to mały ptak lub ćma, ale kiedy próbowałem uchylić trochę bardziej okno, to "coś" zatrzymało się na moskitierze. Nietoperz wcisnął się w szczelinę pomiędzy dachem Sprintera, a drewnianym sufitem i poszedł spać na cały dzień. Swoją drogą tak dowiedzieliśmy się, że jest tam przejście znad moskitiery pod dach i trzeba się tym zająć. diff --git a/src/data/post.ts b/src/data/post.ts index 7cadb93..85cc0d0 100644 --- a/src/data/post.ts +++ b/src/data/post.ts @@ -1,16 +1,18 @@ import { type CollectionEntry, getCollection } from "astro:content"; -/** filter out draft posts based on the environment and optionally archived posts and micro posts */ -export async function getAllPosts( - includeArchived = false, - includeMicro = false, -): Promise<CollectionEntry<"post">[]> { - return await getCollection("post", ({ data }) => { +/** filter out draft posts based on the environment and optionally archived posts */ +export async function getAllPosts(includeArchived = false): Promise<CollectionEntry<"post">[]> { + const posts = await getCollection("post", ({ data }) => { const isDraftFilter = import.meta.env.PROD ? !data.draft : true; const isArchivedFilter = includeArchived || !data.tags.includes("archived"); - const isMicroFilter = includeMicro || !data.tags.includes("micro"); - return isDraftFilter && isArchivedFilter && isMicroFilter; + return isDraftFilter && isArchivedFilter; }); + + // Fetch pleroma posts and cast them to post type since schemas are now compatible + const pleromaPosts = await getCollection("pleroma").catch(() => []); + const pleromaAsPost = pleromaPosts as unknown as CollectionEntry<"post">[]; + + return [...posts, ...pleromaAsPost]; } /** Get tag metadata by tag name */ diff --git a/src/layouts/BlogPost.astro b/src/layouts/BlogPost.astro index 9c60900..59f7282 100644 --- a/src/layouts/BlogPost.astro +++ b/src/layouts/BlogPost.astro @@ -33,6 +33,20 @@ const readingTime: string = remarkPluginFrontmatter.readingTime; > <slot /> <WebMentions /> + { + post.data.sourceUrl && ( + <p class="mt-8 border-t border-gray-200 pt-6 text-sm dark:border-gray-700"> + <a + href={post.data.sourceUrl} + class="cactus-link" + target="_blank" + rel="noopener noreferrer" + > + View original post on Pleroma → + </a> + </p> + ) + } </div> </article> <button diff --git a/src/loaders/pleroma.ts b/src/loaders/pleroma.ts index c57a22b..b3fa8ff 100644 --- a/src/loaders/pleroma.ts +++ b/src/loaders/pleroma.ts @@ -265,12 +265,8 @@ function extractTrailingHashtags(content: string): { /** * Merge thread posts into a single content structure with image grids per segment */ -function mergeThreadContent(chain: PleromaStatus[]): { - content: string; - attachments: Array<{ url: string; type: string }>; -} { +function mergeThreadContent(chain: PleromaStatus[]): string { const segments: string[] = []; - const allAttachments: Array<{ url: string; type: string }> = []; const allTags = new Set<string>(); // Collect all tags from all segments for (const post of chain) { @@ -286,28 +282,9 @@ function mergeThreadContent(chain: PleromaStatus[]): { let segment = mainContent; // Add image attachments as HTML grid after the text - const imageAttachments = post.media_attachments.filter( - (attachment) => attachment.type === "image", - ); - - if (imageAttachments.length > 0) { - // Build HTML grid for images - const imageGrid = ` -<div class="mt-4 mb-4 grid grid-cols-1 gap-4 sm:grid-cols-2"> -${imageAttachments - .map((attachment) => { - const description = attachment.description || "Image"; - allAttachments.push({ - url: attachment.url, - type: `image/${attachment.url.split(".").pop() || "jpeg"}`, - }); - return `<a href="${attachment.url}" target="_blank" rel="noopener noreferrer" class="block overflow-hidden rounded-lg border border-gray-200 transition-colors hover:border-gray-300 dark:border-gray-700 dark:hover:border-gray-600"> -<img src="${attachment.url}" alt="${description}" class="h-48 w-full object-cover" loading="lazy" /> -</a>`; - }) - .join("\n")} -</div>`; + const imageGrid = buildImageGridHtml(post.media_attachments); + if (imageGrid) { segment = `${segment}\n\n${imageGrid}`; } @@ -323,7 +300,7 @@ ${imageAttachments content = `${content}\n\n${tagLine}`; } - return { content, attachments: [] }; // Return empty attachments to avoid duplicate grid at end + return content; } async function getAccountId( @@ -539,6 +516,30 @@ function cleanContent(htmlContent: string): string { } /** + * Build HTML grid for image attachments + * Returns empty string if no image attachments are provided + */ +function buildImageGridHtml(attachments: PleromaMediaAttachment[]): string { + const imageAttachments = attachments.filter((attachment) => attachment.type === "image"); + + if (imageAttachments.length === 0) { + return ""; + } + + return ` +<div class="mt-4 mb-4 grid grid-cols-1 gap-4 sm:grid-cols-2"> +${imageAttachments + .map((attachment) => { + const description = attachment.description || "Image"; + return `<a href="${attachment.url}" target="_blank" rel="noopener noreferrer" class="block overflow-hidden rounded-lg border border-gray-200 transition-colors hover:border-gray-300 dark:border-gray-700 dark:hover:border-gray-600"> +<img src="${attachment.url}" alt="${description}" class="h-48 w-full object-cover" loading="lazy" /> +</a>`; + }) + .join("\n")} +</div>`; +} + +/** * Replace all hashtags in content with internal tag links * Handles both plain #hashtags and existing markdown links [#tag](url) * Returns modified content and extracted tags array @@ -587,7 +588,7 @@ function replacePleromaLinks( const markdownLinkRegex = new RegExp(`\\[([^\\]]+)\\]\\(${noticePattern}\\)`, "g"); let modifiedContent = content.replace(markdownLinkRegex, (match, linkText, statusId) => { if (existingPostIds.has(statusId)) { - return `[${linkText}](/micro/pleroma-${statusId}/)`; + return `[${linkText}](/posts/pleroma-${statusId}/)`; } return match; // Keep original if post doesn't exist }); @@ -597,7 +598,7 @@ function replacePleromaLinks( const plainUrlRegex = new RegExp(`(?<!\\()${noticePattern}(?!\\))`, "g"); modifiedContent = modifiedContent.replace(plainUrlRegex, (match, statusId) => { if (existingPostIds.has(statusId)) { - return `/micro/pleroma-${statusId}/`; + return `/posts/pleroma-${statusId}/`; } return match; // Keep original if post doesn't exist }); @@ -679,7 +680,6 @@ export function pleromaLoader(config: PleromaFeedConfig): Loader { try { const content = status.content || ""; let cleanedContent: string; - let attachments: Array<{ url: string; type: string }>; let postId: string; let sourceUrl: string; let tags: string[]; @@ -695,13 +695,14 @@ export function pleromaLoader(config: PleromaFeedConfig): Loader { logger.info(`Built chain with ${chain.length} post(s) for thread ${status.id}`); // Merge thread content - const merged = mergeThreadContent(chain); - const { content: contentWithTags, tags: extractedTags } = replaceHashtagsWithLinks( - merged.content, - ); - tags = [...extractedTags, "micro"]; + const mergedContent = mergeThreadContent(chain); + const { content: contentWithTags, tags: extractedTags } = + replaceHashtagsWithLinks(mergedContent); + // Add microblog tag if not already present + tags = extractedTags.includes("microblog") + ? extractedTags + : [...extractedTags, "microblog"]; cleanedContent = replacePleromaLinks(contentWithTags, instanceUrl, allPostIds); - attachments = merged.attachments; postId = status.id; sourceUrl = status.url; } else { @@ -709,31 +710,26 @@ export function pleromaLoader(config: PleromaFeedConfig): Loader { const rawContent = cleanContent(content); const { content: contentWithTags, tags: extractedTags } = replaceHashtagsWithLinks(rawContent); - tags = [...extractedTags, "micro"]; - cleanedContent = replacePleromaLinks(contentWithTags, instanceUrl, allPostIds); + // Add microblog tag if not already present + tags = extractedTags.includes("microblog") + ? extractedTags + : [...extractedTags, "microblog"]; + const contentWithLinks = replacePleromaLinks( + contentWithTags, + instanceUrl, + allPostIds, + ); + + // Build image grid HTML and append to content for RSS feeds + const imageGrid = buildImageGridHtml(status.media_attachments); + cleanedContent = imageGrid ? `${contentWithLinks}\n\n${imageGrid}` : contentWithLinks; + postId = status.id; sourceUrl = status.url; - - // Extract image attachments only - attachments = status.media_attachments - .filter((attachment) => attachment.type === "image") - .map((attachment) => ({ - url: attachment.url, - type: `image/${attachment.url.split(".").pop() || "jpeg"}`, - alt: attachment.description || undefined, - })); } const title = extractTitle(cleanedContent); - // Extract author information from status account - const author = { - username: status.account.username, - displayName: status.account.display_name || undefined, - acct: status.account.acct, - url: status.account.url || undefined, - }; - // Create note entry store.set({ id: `pleroma-${postId}`, @@ -743,10 +739,10 @@ export function pleromaLoader(config: PleromaFeedConfig): Loader { cleanedContent.substring(0, 160) + (cleanedContent.length > 160 ? "..." : ""), publishDate: new Date(status.created_at), sourceUrl, - author, - attachments, language: status.language || undefined, tags, + draft: false, + author: "Dawid", }, body: cleanedContent, rendered: { diff --git a/src/pages/index.astro b/src/pages/index.astro index 1bc088c..e3884ef 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,23 +1,27 @@ --- -import { type CollectionEntry, getCollection } from "astro:content"; +import type { CollectionEntry } from "astro:content"; import PostPreview from "@/components/blog/PostPreview.astro"; -import Note from "@/components/note/Note.astro"; import SocialList from "@/components/SocialList.astro"; import { getAllPosts } from "@/data/post"; import PageLayout from "@/layouts/Base.astro"; import { collectionDateSort } from "@/utils/date"; -// Posts -const MAX_POSTS = 10; +// Get all posts const allPosts = await getAllPosts(); -const allPostsByDate = allPosts + +// Posts section - exclude archived and microblog +const MAX_POSTS = 10; +const regularPosts = allPosts.filter( + (post) => !post.data.tags.includes("archived") && !post.data.tags.includes("microblog"), +); +const allPostsByDate = regularPosts .sort(collectionDateSort) .slice(0, MAX_POSTS) as CollectionEntry<"post">[]; -// Micro -const MAX_MICRO = 5; -const allMicro = await getCollection("micro").catch(() => []); // Fallback to empty array if micro collection fails -const latestMicro = allMicro.sort(collectionDateSort).slice(0, MAX_MICRO); +// Microblog posts section - only posts with microblog tag +const MAX_MICROBLOG = 5; +const allMicroblogPosts = allPosts.filter((post) => post.data.tags.includes("microblog")); +const latestMicroblog = allMicroblogPosts.sort(collectionDateSort).slice(0, MAX_MICROBLOG); --- <PageLayout meta={{ title: "Home" }}> @@ -46,15 +50,15 @@ const latestMicro = allMicro.sort(collectionDateSort).slice(0, MAX_MICRO); </ul> </section> { - latestMicro.length > 0 && ( + latestMicroblog.length > 0 && ( <section class="mt-16"> <h2 class="title text-accent mb-6 text-xl"> - <a href="/tags/micro/">Micro</a> + <a href="/tags/microblog/">Microblog</a> </h2> <ul class="space-y-6" role="list"> - {latestMicro.map((note) => ( - <li> - <Note note={note} as="h3" isPreview /> + {latestMicroblog.map((post) => ( + <li class="grid gap-2 sm:grid-cols-[auto_1fr]"> + <PostPreview post={post} as="h3" /> </li> ))} </ul> diff --git a/src/pages/micro/[...slug].astro b/src/pages/micro/[...slug].astro deleted file mode 100644 index 681c106..0000000 --- a/src/pages/micro/[...slug].astro +++ /dev/null @@ -1,34 +0,0 @@ ---- -import { getCollection } from "astro:content"; -import type { GetStaticPaths, InferGetStaticPropsType } from "astro"; -import Note from "@/components/note/Note.astro"; -import PageLayout from "@/layouts/Base.astro"; -import { siteConfig } from "@/site.config"; - -// if you're using an adaptor in SSR mode, getStaticPaths wont work -> https://docs.astro.build/en/guides/routing/#modifying-the-slug-example-for-ssr -export const getStaticPaths = (async () => { - // Get only Pleroma posts - const allMicro = await getCollection("micro").catch(() => []); // Fallback to empty array if micro collection fails - - return allMicro.map((post) => ({ - params: { slug: post.id }, - props: { note: post }, // Keep 'note' name for compatibility with existing component - })); -}) satisfies GetStaticPaths; - -export type Props = InferGetStaticPropsType<typeof getStaticPaths>; - -const { note } = Astro.props; - -const meta = { - description: - note.data.description || - `Read about my note posted on: ${note.data.publishDate.toLocaleDateString()}`, - title: note.data.title, - lang: note.data.language || siteConfig.lang, -}; ---- - -<PageLayout meta={meta}> - <Note as="h1" note={note} /> -</PageLayout> diff --git a/src/pages/posts/[...page].astro b/src/pages/posts/[...page].astro index acca040..d318525 100644 --- a/src/pages/posts/[...page].astro +++ b/src/pages/posts/[...page].astro @@ -12,7 +12,11 @@ export const getStaticPaths = (async ({ paginate }) => { const MAX_POSTS_PER_PAGE = 10; const MAX_TAGS = 7; const allPosts = await getAllPosts(); - const sortedPosts = allPosts.sort(collectionDateSort); + // Filter out archived and microblog posts from main posts page + const filteredPosts = allPosts.filter( + (post) => !post.data.tags.includes("archived") && !post.data.tags.includes("microblog"), + ); + const sortedPosts = filteredPosts.sort(collectionDateSort); const uniqueTags = getUniqueTags(sortedPosts).slice(0, MAX_TAGS); return paginate(sortedPosts, { pageSize: MAX_POSTS_PER_PAGE, diff --git a/src/pages/rss.xml.ts b/src/pages/rss.xml.ts index 39f3964..d428cc9 100644 --- a/src/pages/rss.xml.ts +++ b/src/pages/rss.xml.ts @@ -15,6 +15,7 @@ export const GET = async (context: APIContext) => { description: post.data.description, pubDate: post.data.publishDate, link: `posts/${post.id}/`, + author: post.data.author, })), customData: `<atom:link href="${context.site}rss.xml" rel="self" type="application/rss+xml" xmlns:atom="http://www.w3.org/2005/Atom" />`, }); diff --git a/src/pages/tags/[tag]/[...page].astro b/src/pages/tags/[tag]/[...page].astro index 9556309..8ae9716 100644 --- a/src/pages/tags/[tag]/[...page].astro +++ b/src/pages/tags/[tag]/[...page].astro @@ -1,35 +1,27 @@ --- -import { getCollection, render } from "astro:content"; +import { render } from "astro:content"; import type { GetStaticPaths, InferGetStaticPropsType } from "astro"; import { Icon } from "astro-icon/components"; import PostPreview from "@/components/blog/PostPreview.astro"; -import Note from "@/components/note/Note.astro"; import Pagination from "@/components/Paginator.astro"; import { getAllPosts, getTagMeta, getUniqueTags } from "@/data/post"; import PageLayout from "@/layouts/Base.astro"; import { collectionDateSort } from "@/utils/date"; -import { getUniqueMicroTags } from "@/utils/micro"; export const getStaticPaths = (async ({ paginate }) => { - const allPosts = await getAllPosts(true, true); // Include archived and micro posts for tag filtering - const allMicro = await getCollection("micro", ({ data }) => data.tags?.includes("micro")).catch( - () => [], - ); + const allPosts = await getAllPosts(true); // Include archived posts (now includes pleroma too) - // Get unique tags from both collections - const postTags = getUniqueTags(allPosts); - const microTags = getUniqueMicroTags(allMicro); - const allTags = [...new Set([...postTags, ...microTags])]; + // Get unique tags from all posts + const allTags = getUniqueTags(allPosts); return allTags.flatMap((tag) => { - // Filter posts and micro posts by tag + // Filter posts by tag const postsWithTag = allPosts.filter((post) => post.data.tags.includes(tag)); - const microWithTag = allMicro.filter((micro) => micro.data.tags?.includes(tag)); - // Combine and sort chronologically - const allItems = [...postsWithTag, ...microWithTag].sort(collectionDateSort); + // Sort chronologically + const sortedPosts = postsWithTag.sort(collectionDateSort); - return paginate(allItems, { + return paginate(sortedPosts, { pageSize: 10, params: { tag }, }); @@ -55,13 +47,13 @@ const meta = { const paginationProps = { ...(page.url.prev && { prevUrl: { - text: "← Previous Tags", + text: "← Previous posts", url: page.url.prev, }, }), ...(page.url.next && { nextUrl: { - text: "Next Tags →", + text: "Next posts →", url: page.url.next, }, }), @@ -96,17 +88,11 @@ const paginationProps = { </div> <ul class="space-y-6"> { - page.data.map((item) => - item.collection === "post" ? ( - <li class="grid gap-2 sm:grid-cols-[auto_1fr]"> - <PostPreview as="h2" post={item} /> - </li> - ) : ( - <li> - <Note note={item} as="h2" isPreview /> - </li> - ), - ) + page.data.map((post) => ( + <li class="grid gap-2 sm:grid-cols-[auto_1fr]"> + <PostPreview as="h2" post={post} /> + </li> + )) } </ul> <Pagination {...paginationProps} /> diff --git a/src/pages/tags/[tag]/rss.xml.ts b/src/pages/tags/[tag]/rss.xml.ts index 3fc8ff3..3a61414 100644 --- a/src/pages/tags/[tag]/rss.xml.ts +++ b/src/pages/tags/[tag]/rss.xml.ts @@ -1,21 +1,14 @@ -import { getCollection } from "astro:content"; import rss from "@astrojs/rss"; import type { APIContext } from "astro"; import { getAllPosts, getUniqueTags } from "@/data/post"; import { siteConfig } from "@/site.config"; -import { getUniqueMicroTags } from "@/utils/micro"; export async function getStaticPaths() { - // Get all posts (including archived) and micro posts to extract all possible tags - const allPosts = await getAllPosts(true, true); // Include archived and micro - const allMicro = await getCollection("micro", ({ data }) => data.tags?.includes("micro")).catch( - () => [], - ); + // Get all posts (including archived, now includes pleroma too) + const allPosts = await getAllPosts(true); - // Get unique tags from both collections - const postTags = getUniqueTags(allPosts); - const microTags = getUniqueMicroTags(allMicro); - const allTags = [...new Set([...postTags, ...microTags])]; + // Get unique tags from all posts + const allTags = getUniqueTags(allPosts); return allTags.map((tag) => ({ params: { tag }, @@ -29,33 +22,14 @@ export const GET = async (context: APIContext) => { throw new Error("Tag parameter is required"); } - // Get posts with this tag (include archived and micro) - const allPosts = await getAllPosts(true, true); + // Get posts with this tag (include archived) + const allPosts = await getAllPosts(true); const postsWithTag = allPosts.filter((post) => post.data.tags.includes(tag)); - // Get micro posts with this tag - const allMicro = await getCollection("micro", ({ data }) => data.tags?.includes("micro")).catch( - () => [], + // Sort chronologically + const sortedPosts = postsWithTag.sort( + (a, b) => b.data.publishDate.getTime() - a.data.publishDate.getTime(), ); - const microWithTag = allMicro.filter((micro) => micro.data.tags?.includes(tag)); - - // Combine and sort chronologically - const allItems = [ - ...postsWithTag.map((post) => ({ - title: post.data.title, - description: post.data.description, - pubDate: post.data.publishDate, - link: `posts/${post.id}/`, - content: undefined, - })), - ...microWithTag.map((micro) => ({ - title: micro.data.title, - description: micro.data.description, - pubDate: micro.data.publishDate, - link: `micro/${micro.id}/`, - content: micro.rendered?.html || micro.body || "", - })), - ].sort((a, b) => b.pubDate.getTime() - a.pubDate.getTime()); const site = context.site || import.meta.env.SITE; @@ -63,7 +37,13 @@ export const GET = async (context: APIContext) => { title: `${siteConfig.title} - ${tag}`, description: `Posts tagged with ${tag}`, site, - items: allItems, + items: sortedPosts.map((post) => ({ + title: post.data.title, + description: post.data.description, + pubDate: post.data.publishDate, + link: `posts/${post.id}/`, + author: post.data.author, + })), customData: `<atom:link href="${site}tags/${tag}/rss.xml" rel="self" type="application/rss+xml" xmlns:atom="http://www.w3.org/2005/Atom" />`, }); }; diff --git a/src/pages/tags/index.astro b/src/pages/tags/index.astro index 2c7b07b..260a4fa 100644 --- a/src/pages/tags/index.astro +++ b/src/pages/tags/index.astro @@ -1,29 +1,12 @@ --- -import { getCollection } from "astro:content"; import { getAllPosts, getUniqueTagsWithCount } from "@/data/post"; import PageLayout from "@/layouts/Base.astro"; -import { getUniqueMicroTagsWithCount } from "@/utils/micro"; -const allPostsIncludingArchived = await getAllPosts(true, true); // Include archived and micro -const allMicro = await getCollection("micro", ({ data }) => data.tags?.includes("micro")).catch( - () => [], -); +// Get all posts including archived (now includes pleroma posts too) +const allPostsIncludingArchived = await getAllPosts(true); -// Get tags with counts from both collections -const postTags = getUniqueTagsWithCount(allPostsIncludingArchived); -const microTags = getUniqueMicroTagsWithCount(allMicro); - -// Merge tags and sum counts -const tagMap = new Map<string, number>(); -for (const [tag, count] of postTags) { - tagMap.set(tag, count); -} -for (const [tag, count] of microTags) { - tagMap.set(tag, (tagMap.get(tag) || 0) + count); -} - -// Convert back to array and sort by count -const allTags = Array.from(tagMap.entries()).sort((a, b) => b[1] - a[1]); +// Get tags with counts from all posts +const allTags = getUniqueTagsWithCount(allPostsIncludingArchived); const meta = { description: "A list of all the topics I've written about in my posts", diff --git a/src/site.config.ts b/src/site.config.ts index d9b395c..d2fa871 100644 --- a/src/site.config.ts +++ b/src/site.config.ts @@ -46,8 +46,8 @@ export const menuLinks: { path: string; title: string }[] = [ title: "Blog", }, { - path: "/tags/micro/", - title: "Micro", + path: "/tags/microblog/", + title: "Microblog", }, { path: "/privacy-policy/", diff --git a/src/utils/date.ts b/src/utils/date.ts index b8c0376..314a837 100644 --- a/src/utils/date.ts +++ b/src/utils/date.ts @@ -15,9 +15,6 @@ export function getFormattedDate( }).format(date); } -export function collectionDateSort( - a: CollectionEntry<"post" | "micro">, - b: CollectionEntry<"post" | "micro">, -) { +export function collectionDateSort(a: CollectionEntry<"post">, b: CollectionEntry<"post">) { return b.data.publishDate.getTime() - a.data.publishDate.getTime(); } diff --git a/src/utils/micro.ts b/src/utils/micro.ts deleted file mode 100644 index 7f06b41..0000000 --- a/src/utils/micro.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { CollectionEntry } from "astro:content"; - -export type MicroEntry = CollectionEntry<"micro">; - -export function sortMicroEntries(entries: MicroEntry[]): MicroEntry[] { - return entries.sort((a, b) => b.data.publishDate.getTime() - a.data.publishDate.getTime()); -} - -export async function getAllMicroPosts(): Promise<MicroEntry[]> { - const { getCollection } = await import("astro:content"); - - // Get only Pleroma micro posts - try { - const microPosts = await getCollection("micro"); - return sortMicroEntries(microPosts); - } catch (error) { - console.warn("Micro collection not available:", error); - return []; - } -} - -/** Extract all tags from micro posts */ -export function getAllMicroTags(entries: MicroEntry[]): string[] { - return entries.flatMap((entry) => entry.data.tags ?? []); -} - -/** Get unique tags from micro posts */ -export function getUniqueMicroTags(entries: MicroEntry[]): string[] { - return [...new Set(getAllMicroTags(entries))]; -} - -/** Get unique tags with counts from micro posts */ -export function getUniqueMicroTagsWithCount(entries: MicroEntry[]): [string, number][] { - return [ - ...getAllMicroTags(entries).reduce( - (acc, t) => acc.set(t, (acc.get(t) ?? 0) + 1), - new Map<string, number>(), - ), - ].sort((a, b) => b[1] - a[1]); -} |
