1
0
Fork 0

It's not pretty but it works

This commit is contained in:
Leon Grünewald 2024-10-23 23:21:27 +02:00
parent c4cf867689
commit 4e507a01c6
16 changed files with 323 additions and 560 deletions

View file

@ -61,8 +61,8 @@ importers:
specifier: ^5.0.5
version: 5.0.5
svelte-check:
specifier: ^3.8.6
version: 3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47))(postcss@8.4.47)(svelte@5.0.5)
specifier: ^4.0.0
version: 4.0.5(picomatch@2.3.1)(svelte@5.0.5)(typescript@5.6.3)
svelte-fa:
specifier: ^4.0.3
version: 4.0.3(svelte@5.0.5)
@ -486,9 +486,6 @@ packages:
'@types/estree@1.0.6':
resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
'@types/pug@2.0.10':
resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==}
acorn-typescript@1.4.13:
resolution: {integrity: sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==}
peerDependencies:
@ -547,9 +544,6 @@ packages:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'}
brace-expansion@1.1.11:
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
brace-expansion@2.0.1:
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
@ -562,10 +556,6 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
buffer-crc32@1.0.0:
resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==}
engines: {node: '>=8.0.0'}
camelcase-css@2.0.1:
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
engines: {node: '>= 6'}
@ -577,6 +567,10 @@ packages:
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
engines: {node: '>= 8.10.0'}
chokidar@4.0.1:
resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==}
engines: {node: '>= 14.16.0'}
color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
@ -588,9 +582,6 @@ packages:
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
engines: {node: '>= 6'}
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
cookie@0.6.0:
resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
engines: {node: '>= 0.6'}
@ -617,10 +608,6 @@ packages:
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
engines: {node: '>=0.10.0'}
detect-indent@6.1.0:
resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
engines: {node: '>=8'}
devalue@5.1.1:
resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==}
@ -642,9 +629,6 @@ packages:
emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
es6-promise@3.3.1:
resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==}
esbuild@0.21.5:
resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
engines: {node: '>=12'}
@ -667,6 +651,14 @@ packages:
fastq@1.17.1:
resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
fdir@6.4.2:
resolution: {integrity: sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==}
peerDependencies:
picomatch: ^3 || ^4
peerDependenciesMeta:
picomatch:
optional: true
fill-range@7.1.1:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
@ -678,9 +670,6 @@ packages:
fraction.js@4.3.7:
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@ -701,19 +690,12 @@ packages:
resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
hasBin: true
glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
deprecated: Glob versions prior to v9 are no longer supported
globalyzer@0.1.0:
resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==}
globrex@0.1.2:
resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==}
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
hasown@2.0.2:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
@ -721,13 +703,6 @@ packages:
import-meta-resolve@4.1.0:
resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==}
inflight@1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
is-binary-path@2.1.0:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
engines: {node: '>=8'}
@ -797,28 +772,14 @@ packages:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
min-indent@1.0.1:
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
engines: {node: '>=4'}
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
minimatch@9.0.5:
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
engines: {node: '>=16 || 14 >=14.17'}
minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
minipass@7.1.2:
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
engines: {node: '>=16 || 14 >=14.17'}
mkdirp@0.5.6:
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
hasBin: true
mri@1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'}
@ -857,16 +818,9 @@ packages:
resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
engines: {node: '>= 6'}
once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
path-is-absolute@1.0.1:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'}
path-key@3.1.1:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
@ -959,6 +913,10 @@ packages:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'}
readdirp@4.0.2:
resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==}
engines: {node: '>= 14.16.0'}
resolve@1.22.8:
resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
hasBin: true
@ -967,11 +925,6 @@ packages:
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
rimraf@2.7.1:
resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==}
deprecated: Rimraf versions prior to v4 are no longer supported
hasBin: true
rollup@4.24.0:
resolution: {integrity: sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@ -984,9 +937,6 @@ packages:
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
engines: {node: '>=6'}
sander@0.5.1:
resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==}
set-cookie-parser@2.7.1:
resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==}
@ -1006,10 +956,6 @@ packages:
resolution: {integrity: sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==}
engines: {node: '>=18'}
sorcery@0.11.1:
resolution: {integrity: sha512-o7npfeJE6wi6J9l0/5LKshFzZ2rMatRiCDwYeDQaOzqdzRJwALhX7mk/A/ecg6wjMu7wdZbmXfD2S/vpOg0bdQ==}
hasBin: true
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
@ -1030,10 +976,6 @@ packages:
resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
engines: {node: '>=12'}
strip-indent@3.0.0:
resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
engines: {node: '>=8'}
sucrase@3.35.0:
resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
engines: {node: '>=16 || 14 >=14.17'}
@ -1043,54 +985,19 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
svelte-check@3.8.6:
resolution: {integrity: sha512-ij0u4Lw/sOTREP13BdWZjiXD/BlHE6/e2e34XzmVmsp5IN4kVa3PWP65NM32JAgwjZlwBg/+JtiNV1MM8khu0Q==}
svelte-check@4.0.5:
resolution: {integrity: sha512-icBTBZ3ibBaywbXUat3cK6hB5Du+Kq9Z8CRuyLmm64XIe2/r+lQcbuBx/IQgsbrC+kT2jQ0weVpZSSRIPwB6jQ==}
engines: {node: '>= 18.0.0'}
hasBin: true
peerDependencies:
svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0
svelte: ^4.0.0 || ^5.0.0-next.0
typescript: '>=5.0.0'
svelte-fa@4.0.3:
resolution: {integrity: sha512-saZ8yACM0k9Aexey+2NXU1W0MBosU5lBsRgqFCJKM+Taw7d0HyimPaPAjmvY/Xkyi3UwEYL/Sdu1IZJv/p0Flw==}
peerDependencies:
svelte: ^4.0.0 || ^5.0.0
svelte-preprocess@5.1.4:
resolution: {integrity: sha512-IvnbQ6D6Ao3Gg6ftiM5tdbR6aAETwjhHV+UKGf5bHGYR69RQvF1ho0JKPcbUON4vy4R7zom13jPjgdOWCQ5hDA==}
engines: {node: '>= 16.0.0'}
peerDependencies:
'@babel/core': ^7.10.2
coffeescript: ^2.5.1
less: ^3.11.3 || ^4.0.0
postcss: ^7 || ^8
postcss-load-config: ^2.1.0 || ^3.0.0 || ^4.0.0 || ^5.0.0
pug: ^3.0.0
sass: ^1.26.8
stylus: ^0.55.0
sugarss: ^2.0.0 || ^3.0.0 || ^4.0.0
svelte: ^3.23.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0
typescript: '>=3.9.5 || ^4.0.0 || ^5.0.0'
peerDependenciesMeta:
'@babel/core':
optional: true
coffeescript:
optional: true
less:
optional: true
postcss:
optional: true
postcss-load-config:
optional: true
pug:
optional: true
sass:
optional: true
stylus:
optional: true
sugarss:
optional: true
typescript:
optional: true
svelte@5.0.5:
resolution: {integrity: sha512-f4WBlP5g8W6pEoDfx741lewMlemy+LIGpEqjGPWqnHVP92wqlQXl87U5O5Bi2tkSUrO95OxOoqwU8qlqiHmFKA==}
engines: {node: '>=18'}
@ -1187,9 +1094,6 @@ packages:
resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
engines: {node: '>=12'}
wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
yaml@2.6.0:
resolution: {integrity: sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==}
engines: {node: '>= 14'}
@ -1496,8 +1400,6 @@ snapshots:
'@types/estree@1.0.6': {}
'@types/pug@2.0.10': {}
acorn-typescript@1.4.13(acorn@8.13.0):
dependencies:
acorn: 8.13.0
@ -1541,11 +1443,6 @@ snapshots:
binary-extensions@2.3.0: {}
brace-expansion@1.1.11:
dependencies:
balanced-match: 1.0.2
concat-map: 0.0.1
brace-expansion@2.0.1:
dependencies:
balanced-match: 1.0.2
@ -1561,8 +1458,6 @@ snapshots:
node-releases: 2.0.18
update-browserslist-db: 1.1.1(browserslist@4.24.2)
buffer-crc32@1.0.0: {}
camelcase-css@2.0.1: {}
caniuse-lite@1.0.30001669: {}
@ -1579,6 +1474,10 @@ snapshots:
optionalDependencies:
fsevents: 2.3.3
chokidar@4.0.1:
dependencies:
readdirp: 4.0.2
color-convert@2.0.1:
dependencies:
color-name: 1.1.4
@ -1587,8 +1486,6 @@ snapshots:
commander@4.1.1: {}
concat-map@0.0.1: {}
cookie@0.6.0: {}
cross-spawn@7.0.3:
@ -1605,8 +1502,6 @@ snapshots:
deepmerge@4.3.1: {}
detect-indent@6.1.0: {}
devalue@5.1.1: {}
didyoumean@1.2.2: {}
@ -1621,8 +1516,6 @@ snapshots:
emoji-regex@9.2.2: {}
es6-promise@3.3.1: {}
esbuild@0.21.5:
optionalDependencies:
'@esbuild/aix-ppc64': 0.21.5
@ -1670,6 +1563,10 @@ snapshots:
dependencies:
reusify: 1.0.4
fdir@6.4.2(picomatch@2.3.1):
optionalDependencies:
picomatch: 2.3.1
fill-range@7.1.1:
dependencies:
to-regex-range: 5.0.1
@ -1681,8 +1578,6 @@ snapshots:
fraction.js@4.3.7: {}
fs.realpath@1.0.0: {}
fsevents@2.3.3:
optional: true
@ -1705,34 +1600,16 @@ snapshots:
package-json-from-dist: 1.0.1
path-scurry: 1.11.1
glob@7.2.3:
dependencies:
fs.realpath: 1.0.0
inflight: 1.0.6
inherits: 2.0.4
minimatch: 3.1.2
once: 1.4.0
path-is-absolute: 1.0.1
globalyzer@0.1.0: {}
globrex@0.1.2: {}
graceful-fs@4.2.11: {}
hasown@2.0.2:
dependencies:
function-bind: 1.1.2
import-meta-resolve@4.1.0: {}
inflight@1.0.6:
dependencies:
once: 1.4.0
wrappy: 1.0.2
inherits@2.0.4: {}
is-binary-path@2.1.0:
dependencies:
binary-extensions: 2.3.0
@ -1788,24 +1665,12 @@ snapshots:
braces: 3.0.3
picomatch: 2.3.1
min-indent@1.0.1: {}
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.11
minimatch@9.0.5:
dependencies:
brace-expansion: 2.0.1
minimist@1.2.8: {}
minipass@7.1.2: {}
mkdirp@0.5.6:
dependencies:
minimist: 1.2.8
mri@1.2.0: {}
mrmime@2.0.0: {}
@ -1830,14 +1695,8 @@ snapshots:
object-hash@3.0.0: {}
once@1.4.0:
dependencies:
wrappy: 1.0.2
package-json-from-dist@1.0.1: {}
path-is-absolute@1.0.1: {}
path-key@3.1.1: {}
path-parse@1.0.7: {}
@ -1910,6 +1769,8 @@ snapshots:
dependencies:
picomatch: 2.3.1
readdirp@4.0.2: {}
resolve@1.22.8:
dependencies:
is-core-module: 2.15.1
@ -1918,10 +1779,6 @@ snapshots:
reusify@1.0.4: {}
rimraf@2.7.1:
dependencies:
glob: 7.2.3
rollup@4.24.0:
dependencies:
'@types/estree': 1.0.6
@ -1952,13 +1809,6 @@ snapshots:
dependencies:
mri: 1.2.0
sander@0.5.1:
dependencies:
es6-promise: 3.3.1
graceful-fs: 4.2.11
mkdirp: 0.5.6
rimraf: 2.7.1
set-cookie-parser@2.7.1: {}
shebang-command@2.0.0:
@ -1975,13 +1825,6 @@ snapshots:
mrmime: 2.0.0
totalist: 3.0.1
sorcery@0.11.1:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.0
buffer-crc32: 1.0.0
minimist: 1.2.8
sander: 0.5.1
source-map-js@1.2.1: {}
string-width@4.2.3:
@ -2004,10 +1847,6 @@ snapshots:
dependencies:
ansi-regex: 6.1.0
strip-indent@3.0.0:
dependencies:
min-indent: 1.0.1
sucrase@3.35.0:
dependencies:
'@jridgewell/gen-mapping': 0.3.5
@ -2020,43 +1859,22 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {}
svelte-check@3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47))(postcss@8.4.47)(svelte@5.0.5):
svelte-check@4.0.5(picomatch@2.3.1)(svelte@5.0.5)(typescript@5.6.3):
dependencies:
'@jridgewell/trace-mapping': 0.3.25
chokidar: 3.6.0
chokidar: 4.0.1
fdir: 6.4.2(picomatch@2.3.1)
picocolors: 1.1.1
sade: 1.8.1
svelte: 5.0.5
svelte-preprocess: 5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47))(postcss@8.4.47)(svelte@5.0.5)(typescript@5.6.3)
typescript: 5.6.3
transitivePeerDependencies:
- '@babel/core'
- coffeescript
- less
- postcss
- postcss-load-config
- pug
- sass
- stylus
- sugarss
- picomatch
svelte-fa@4.0.3(svelte@5.0.5):
dependencies:
svelte: 5.0.5
svelte-preprocess@5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47))(postcss@8.4.47)(svelte@5.0.5)(typescript@5.6.3):
dependencies:
'@types/pug': 2.0.10
detect-indent: 6.1.0
magic-string: 0.30.12
sorcery: 0.11.1
strip-indent: 3.0.0
svelte: 5.0.5
optionalDependencies:
postcss: 8.4.47
postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.47)
typescript: 5.6.3
svelte@5.0.5:
dependencies:
'@ampproject/remapping': 2.3.0
@ -2159,8 +1977,6 @@ snapshots:
string-width: 5.1.2
strip-ansi: 7.1.0
wrappy@1.0.2: {}
yaml@2.6.0: {}
zimmerframe@1.1.2: {}

View file

@ -2,7 +2,7 @@
"build": {
"beforeDevCommand": "pnpm dev",
"beforeBuildCommand": "pnpm build",
"frontendDist": "../dist",
"frontendDist": "../build",
"devUrl": "http://localhost:1420"
},
"bundle": {

View file

@ -1,6 +1,7 @@
<script>
import { RangeSlider, Tab, TabGroup, InputChip, SlideToggle } from '@skeletonlabs/skeleton';
import { imageGridColumns, postGridPreviewQuality, blacklist, limitImageHeight } from '$lib/settings';
import useSettings from '$lib/useSettings.svelte.js';
const settings = useSettings();
let tabPos = $state(0);
let showApikey = $state(false);
@ -8,32 +9,31 @@
</script>
<div class="flex flex-col">
<h2 class="h2 mb-2 text-dark-token">Settings</h2>
<TabGroup>
<!--<TabGroup>
<Tab class="text-dark-token" bind:group={tabPos} name="tab1" value={0}>Display</Tab>
<Tab class="text-dark-token" bind:group={tabPos} name="tab2" value={1}>API</Tab>
<Tab class="text-dark-token" bind:group={tabPos} name="tab3" value={2}>User</Tab>
<Tab class="text-dark-token" bind:group={tabPos} name="tab4" value={3}>Chats</Tab>
{#snippet panel()}
{#if tabPos === 0}
<div class="flex flex-col gap-3">
<h3 class="h3 text-dark-token font-bold">Image</h3>
<SlideToggle name="image-limit-height" bind:checked={$limitImageHeight}><span class="text-dark-token">Limit image height</span></SlideToggle>
<SlideToggle name="image-limit-height" bind:checked={settings.limitImageHeight}><span class="text-dark-token">Limit image height</span></SlideToggle>
<h3 class="h3 text-dark-token font-bold">Grid</h3>
<div class="basis-1/2">
<RangeSlider accent="text-dark-token" name="grid-columns" min={1} max={12} bind:value={$imageGridColumns} ticked={true}>
<RangeSlider accent="text-dark-token" name="grid-columns" min={1} max={12} bind:value={settings.imageGridColumns} ticked={true}>
<div class="flex flex-grow justify-between items-center dark">
<div class="text-dark-token font-bold mb-1">Grid Columns</div>
<div class="text-xs text-dark-token">{$imageGridColumns} / {12}</div>
<div class="text-xs text-dark-token">{settings.imageGridColumns} / {12}</div>
</div>
</RangeSlider>
</div>
<div class="basis-1/2">
<label class="label">
<span class="text-dark-token font-bold">Preview type</span>
<select class="select" bind:value={$postGridPreviewQuality}>
<select class="select" bind:value={settings.postGridPreviewQuality}>
<option value="preview">Preview</option>
<option value="sample">Sample</option>
</select>
@ -71,7 +71,7 @@
<div class="flex flex-col gap-3">
<div class="">
<p class="text-dark-token font-bold">Blacklist</p>
<InputChip name="blacklist" label="Blacklist" bind:value={$blacklist} />
<InputChip name="blacklist" label="Blacklist" bind:value={settings.blacklist} />
</div>
</div>
{/if}
@ -80,11 +80,10 @@
<div class="flex flex-col gap-3">
<div class="">
<p class="text-dark-token font-bold">Chats</p>
<InputChip name="blacklist" label="Blacklist" bind:value={$blacklist} />
<InputChip name="blacklist" label="Blacklist" bind:value={settings.blacklist} />
</div>
</div>
{/if}
{/snippet}
</TabGroup>
</TabGroup>-->
</div>

View file

@ -1,18 +1,15 @@
<script>
import {faArrowLeft} from '@fortawesome/free-solid-svg-icons';
import {Fa} from 'svelte-fa';
import {AppRailAnchor} from '@skeletonlabs/skeleton';
/**
* @typedef {Object} Props
* @property {number} [popCount]
*/
import {onMount} from "svelte";
/** @type {Props} */
let { popCount = 1 } = $props();
let href = $state();
let pathnameParts = window.location.pathname.split('/');
let pathnameParts = $state(null);
onMount(() => {
pathnameParts = window.location.pathname.split('/')
for(let i = 0; i < popCount; i++) {
pathnameParts.pop();
}
@ -28,12 +25,13 @@ switch (pathnameParts.length) {
href = '/' + pathnameParts.join('/')
break;
}
});
</script>
<AppRailAnchor {href} title="Back">
<a {href} class="h-full aspect-square">
<div class="flex flex-col gap-2 place-content-center">
<Fa size={'2x'} icon={faArrowLeft} />
<p>Back</p>
</div>
</AppRailAnchor>
</a>

View file

@ -1,21 +1,22 @@
<script>
import { preventDefault } from 'svelte/legacy';
import useSettings from '$lib/useSettings.svelte.js';
import {loading} from "$lib/stores.js";
import { showSearch, loading } from '$lib/stores';
import { lastSearch } from '$lib/settings';
import { goto } from '$app/navigation';
let searchValue = $state($lastSearch);
const settings = useSettings();
let searchString = $state('');
const {onsubmit = null} = $props();
$effect(() => {
searchString = settings.lastSearch
});
</script>
{#if $showSearch}
<form class="flex flex-row gap-2"
onsubmit={preventDefault(() => {
$loading = true;
goto('/')
lastSearch.set(searchValue);
})}>
<input class="input py-1 px-2 w-96" type="text" placeholder="Search" bind:value={searchValue} />
onsubmit={(e) => {
e.preventDefault();
settings.lastSearch = searchString;
loading.set(true);
onsubmit?.(searchString, true);
}}>
<input class="input py-1 px-2 w-96" type="text" placeholder="Search" bind:value={searchString} />
<button class="btn btn-md variant-filled" type="submit">Submit</button>
</form>
{/if}

View file

@ -0,0 +1,13 @@
<script>
import {BackAppRailAnchor, GlobalSearch} from "$lib/components";
let {onsubmit = null, back = null} = $props();
</script>
<header class="top-0 fixed flex">
{#if back}
<BackAppRailAnchor popCount={back} />
{/if}
<GlobalSearch onsubmit={(val = '', explicitRefresh = false) => {
onsubmit?.(val, explicitRefresh);
}} />
</header>

View file

@ -1,27 +1,25 @@
<script>
import { showSearch, loading } from '$lib/stores';
import { postGridPreviewQuality, imageGridColumns } from '$lib/settings';
import useSettings from "$lib/useSettings.svelte.js";
import { loading } from "$lib/stores.js";
let { posts = [] } = $props();
const settings = useSettings();
</script>
<div class="grid gap-3" style={`grid-template-columns: repeat(${$imageGridColumns}, minmax(0, 1fr))`}>
<div class="grid gap-3" style={`grid-template-columns: repeat(${settings.imageGridColumns}, minmax(0, 1fr))`}>
{#each posts as post}
<a href={`/posts/${post.id}`} class="card p-3 flex flex-col justify-end items-center" onclick={() => {
$loading = true;
$showSearch = false
loading.set(true);
}}>
<header class="card-header p-0"></header>
<section class="flex flex-col">
<img src={post[$postGridPreviewQuality].url}
<img src={post[settings.postGridPreviewQuality].url}
loading="lazy"
alt={`Post ${post.id}`} />
<div class="bg-black px-2 py-1">
<p class="text-center text-dark-token">{post.id} {post.file.ext} {post.rating}</p>
</div>
</section>
<footer >
</footer>
</a>
{/each}
</div>

View file

@ -1,5 +1,6 @@
<script>
import { limitImageHeight } from '$lib/settings';
import useSettings from '$lib/useSettings.svelte.js';
const settings = useSettings();
/**
* @typedef {Object} Props
@ -11,13 +12,13 @@
</script>
{#if post?.preview?.has}
<img class:max-h-dvh={$limitImageHeight} src={post.preview.url} alt={`Post ${post.id}`} />
<img class:max-h-dvh={settings.limitImageHeight} src={post.preview.url} alt={`Post ${post.id}`} />
{:else}
{#if ['webm', 'mp4'].includes(post.file.ext)}
<video class:max-h-dvh={$limitImageHeight} controls playsinline>
<video class:max-h-dvh={settings.limitImageHeight} controls playsinline>
<source src={post.file.url} />
</video>
{:else}
<img class:max-h-dvh={$limitImageHeight} src={post.file.url} alt={`Post ${post.id}`} />
<img class:max-h-dvh={settings.limitImageHeight} src={post.file.url} alt={`Post ${post.id}`} />
{/if}
{/if}

View file

@ -3,7 +3,7 @@ import BackAppRailAnchor from './BackAppRailAnchor.svelte';
import GlobalSearch from './GlobalSearch.svelte';
import ImageGrid from './ImageGrid.svelte';
import PostMedia from './PostMedia.svelte';
import SearchAppRailAnchor from './SearchAppRailAnchor.svelte';
import Header from './Header.svelte';
export {
AppSettings,
@ -11,5 +11,5 @@ export {
GlobalSearch,
ImageGrid,
PostMedia,
SearchAppRailAnchor
Header,
}

View file

@ -2,4 +2,3 @@ import { writable } from 'svelte/store';
export const postSearchResults = writable(null);
export const loading = writable(false);
export const showSearch = writable(true);

View file

@ -1,8 +0,0 @@
function useLoading() {
let loading = $state(false);
return {
get loading() {return loading},
setLoading: (val) => {loading = val},
toggleLoading: () => {loading = !loading}
}
}

View file

@ -0,0 +1,56 @@
import {onMount} from "svelte";
function initFromLocalStorage(storageKey, initalValue = null) {
return window.localStorage.getItem(storageKey) ?? initalValue;
}
export default function useSettings() {
let lastSearch = $state(null),
imageGridColumns = $state(6),
limitImageHeight = $state(false),
postGridPreviewQuality = $state('preview'),
blacklist = $state([
'gore',
'scat',
'watersports',
'young',
'loli',
'shota',
]);
onMount(() => {
lastSearch = localStorage.getItem('lastSearch') ?? lastSearch;
imageGridColumns = localStorage.getItem('gridColumns') ?? imageGridColumns;
limitImageHeight = localStorage.getItem('limitImageHeight') ?? limitImageHeight;
postGridPreviewQuality = localStorage.getItem('gridPreviewQuality') ?? postGridPreviewQuality;
blacklist = localStorage.getItem('blacklist') ?? blacklist;
})
return {
get lastSearch() {return lastSearch},
get imageGridColumns() {return imageGridColumns},
get postGridPreviewQuality() {return postGridPreviewQuality},
get blacklist() {return blacklist},
get limitImageHeight() {return limitImageHeight},
set lastSearch(val) {
lastSearch = val;
localStorage.setItem('lastSearch', val);
},
set imageGridColumns(val) {
imageGridColumns = val;
localStorage.setItem('gridColumns', val);
},
set postGridPreviewQuality(val) {
postGridPreviewQuality = val
localStorage.setItem('gridPreviewQuality', val);
},
set blacklist(val) {
blacklist = val
localStorage.setItem('blacklist', val);
},
set limitImageHeight(val) {
limitImageHeight = val
localStorage.setItem('limitImageHeight', val);
},
}
}

View file

@ -1,8 +1,6 @@
<script>
import '../app.pcss';
import { Drawer, initializeStores, Modal, ProgressRadial, Toast } from '@skeletonlabs/skeleton';
import { loading } from '$lib/stores';
import { AppSettings } from '$lib/components';
import { loading } from "$lib/stores.js";
/**
* @typedef {Object} Props
* @property {import('svelte').Snippet} [children]
@ -10,22 +8,11 @@
/** @type {Props} */
let { children } = $props();
initializeStores();
</script>
<div class="relative h-dvh">
<Modal />
<Toast />
<Drawer bgDrawer="bg-surface-500/90" width="w-6/12" height="h-dvh" position="left">
<div class="h-full p-4">
<AppSettings />
</div>
</Drawer>
{#if $loading}
<div class="fixed bottom-3 right-3 w-8 h-8">
<ProgressRadial width="w-8" height="h-8" stroke={120} strokeLinecap="butt" />
</div>
<p class="absolute top-0 left-0">Loading</p>
{/if}
{@render children?.()}
</div>

View file

@ -1,84 +1,41 @@
<script>
import { Fa } from 'svelte-fa';
import { GlobalSearch, ImageGrid, SearchAppRailAnchor} from '$lib/components';
import { faGear } from '@fortawesome/free-solid-svg-icons';
import { Header, ImageGrid } from '$lib/components';
import { invoke } from '@tauri-apps/api/core'
import { lastSearch, blacklist } from '$lib/settings';
import { postSearchResults, loading, showSearch} from '$lib/stores';
import {
AppBar,
AppRail,
AppRailAnchor,
AppShell,
getDrawerStore, getToastStore
} from '@skeletonlabs/skeleton';
import PostList from '$lib/PostList';
import useSettings from "$lib/useSettings.svelte.js";
import {onMount} from "svelte";
import {loading, postSearchResults} from "$lib/stores.js";
const drawerStore = getDrawerStore();
let initalSearch = true;
const settings = useSettings();
function onSearch() {
$loading = true;
/*invoke('get_posts', { query: $lastSearch }).then((resPosts) => {
postSearchResults.set(new PostList(resPosts).filterPosts($blacklist).getPosts());
requestAnimationFrame(() => $loading = false);
});*/
function onSearch(val = '', explicitRefresh = false) {
loading.set(true);
invoke('get_posts', { query: val }).then((resPosts) => {
postSearchResults.set(new PostList(resPosts).filterPosts(settings.blacklist).getPosts())
loading.set(false)
});
}
lastSearch.subscribe(() => {
if (initalSearch) {
initalSearch = false;
if ($postSearchResults === null) onSearch();
return
onMount(() => {
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.has('search')) {
onSearch(urlParams.get('search'), false);
return;
}
onSearch();
if ($postSearchResults === null) {
onSearch(settings.lastSearch, true);
}
})
</script>
<AppShell>
{#snippet pageHeader()}
{#if $showSearch}
<AppBar>
<GlobalSearch />
</AppBar>
{/if}
{/snippet}
{#snippet sidebarLeft()}
<div class="h-dvh">
<AppRail>
{#snippet lead()}
<SearchAppRailAnchor />
{/snippet}
{#snippet trail()}
<AppRailAnchor on:click={() => drawerStore.open()}>
<div class="flex flex-col gap-2 place-content-center">
<Fa size={'2x'} icon={faGear} />
<p>Settings</p>
</div>
</AppRailAnchor>
{/snippet}
</AppRail>
</div>
{/snippet}
{#snippet children()}
<div>
<Header onsubmit={(val = '', explicitRefresh = false) => {onSearch(val, explicitRefresh);}}></Header>
<main>
<div class="overflow-scroll p-2">
{#if $postSearchResults}
<ImageGrid posts={$postSearchResults} />
{/if}
</div>
{/snippet}
</AppShell>
</main>
</div>

View file

@ -1,100 +1,35 @@
<script>
import {
AppBar,
AppRail,
AppRailAnchor,
AppShell,
getDrawerStore,
clipboard,
getToastStore
} from '@skeletonlabs/skeleton';
import {faGear, faCopy, faStar, faCaretUp, faCaretDown, faHeart} from '@fortawesome/free-solid-svg-icons';
import { faStar, faCaretUp, faCaretDown, faHeart } from '@fortawesome/free-solid-svg-icons';
import { Fa } from 'svelte-fa';
import { BackAppRailAnchor, GlobalSearch, PostMedia, SearchAppRailAnchor } from '$lib/components';
import { PostMedia } from '$lib/components';
import { onMount } from 'svelte';
import { loading, showSearch } from '$lib/stores';
import { TAG_TYPES } from '$lib/Tags';
import { invoke } from '@tauri-apps/api/core';
import Header from "$lib/components/Header.svelte";
import {goto} from "$app/navigation";
import {loading} from "$lib/stores.js";
let { data } = $props();
const drawerStore = getDrawerStore();
const tagTypes = Object.entries(TAG_TYPES);
const toastStore = getToastStore();
/** @type any|null */
let post = $state(null);
onMount(async () => {
$loading = true;
const postRequest = await invoke('get_post', {postId: +data.postId});
$loading = false;
post = postRequest;
loading.set(true);
post = await invoke('get_post', {postId: +data.postId});
loading.set(false);
});
</script>
<AppShell>
{#snippet pageHeader()}
{#if $showSearch}
<AppBar>
<GlobalSearch />
</AppBar>
{/if}
{/snippet}
{#snippet sidebarRight()}
{#if post}
<div class="p-2 h-dvh">
{#each tagTypes as [name, label]}
<div class="mb-2">
<p class="font-bold">{label}</p>
{#each post.tags[name] as tag}
<p>{tag}</p>
{/each}
</div>
{/each}
</div>
{/if}
{/snippet}
{#snippet sidebarLeft()}
<div class="h-dvh">
<AppRail>
{#snippet lead()}
<BackAppRailAnchor popCount={2} />
<SearchAppRailAnchor />
{/snippet}
{#snippet trail()}
{#if post}
<AppRailAnchor>
<button class="w-full flex flex-col gap-2 place-content-center place-items-center" onclick={() => toastStore.trigger({message: 'Copied link'})} use:clipboard={`https://e621.net/posts/${post.id}`}>
<Fa size={'2x'} icon={faCopy} />
Copy link
</button>
</AppRailAnchor>
{/if}
<AppRailAnchor on:click={() => drawerStore.open()}>
<button class="w-full flex flex-col gap-2 place-content-center place-items-center">
<Fa size={'2x'} icon={faGear} />
Settings
</button>
</AppRailAnchor>
{/snippet}
</AppRail>
</div>
{/snippet}
{#snippet default()}
<div class="grid [grid-template-areas:'main_main_aside''footer_footer_footer']">
<Header back={2} onsubmit={(val = '') => {
const queryParams = new URLSearchParams();
queryParams.set('search', val);
goto("/?" + queryParams.toString())
}}></Header>
<main clasS="h-screen [grid-area-main]">
<div class="container mx-auto flex flex-col items-center justify-center">
{#if post}
<div class="card mb-4 flex flex-col">
@ -135,15 +70,26 @@
<footer class="card-footer pt-4">
<h3 class="font-bold mb-2" class:line-through={post.description === ''} >Description</h3>
<p>{post.description}</p>
<!-- <pre class="break-all">
{JSON.stringify(post, null, 2)}
</pre> -->
</footer>
</div>
{/if}
</div>
</main>
{/snippet}
</AppShell>
<aside class="[grid-area-aside]">
{#if post}
<div class="p-2 h-dvh">
{#each tagTypes as [name, label]}
<div class="mb-2">
<p class="font-bold">{label}</p>
{#each post.tags[name] as tag}
<p>{tag}</p>
{/each}
</div>
{/each}
</div>
{/if}
</aside>
</div>
<style lang="postcss"></style>