extremely wip tangled spa

Compare changes

Choose any two refs to compare.

+17 -3
LICENSE
···
+
MIT License
+
Copyright (c) 2025 aylac.top
-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
Permission is hereby granted, free of charge, to any person obtaining a copy
+
of this software and associated documentation files (the "Software"), to deal
+
in the Software without restriction, including without limitation the rights
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+
copies of the Software, and to permit persons to whom the Software is
+
furnished to do so, subject to the following conditions:
-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
The above copyright notice and this permission notice shall be included in all
+
copies or substantial portions of the Software.
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+
SOFTWARE.
+2 -1
biome.json
···
"style": { "noNonNullAssertion": "off" }
},
"domains": {
-
"solid": "recommended"
+
"solid": "all",
+
"react": "none"
}
},
"javascript": {
+135 -175
bun.lock
···
"": {
"name": "vite-template-solid",
"dependencies": {
-
"@atcute/atproto": "^3.1.9",
"@atcute/client": "^4.0.5",
"@atcute/identity-resolver": "^1.1.4",
"@atcute/oauth-browser-client": "^2.0.1",
-
"@atcute/tangled": "^1.0.10",
"@gleam-lang/highlight.js-gleam": "^1.5.0",
"@solidjs/router": "^0.15.3",
"@tailwindcss/vite": "^4.1.17",
···
"solid-markdown": "^2.0.14",
},
"devDependencies": {
-
"@biomejs/biome": "^2.3.4",
+
"@atcute/atproto": "^3.1.9",
+
"@atcute/lexicons": "^1.2.3",
+
"@atcute/microcosm": "^1.0.0",
+
"@atcute/tangled": "^1.0.12",
+
"@biomejs/biome": "^2.3.6",
"@iconify-json/gravity-ui": "^1.2.10",
"@iconify/tailwind4": "^1.1.0",
"postcss": "^8.5.6",
"solid-devtools": "^0.34.4",
"tailwindcss": "^4.1.17",
-
"vite": "^7.2.2",
+
"vite": "^7.2.4",
"vite-plugin-solid": "^2.11.10",
},
},
···
"@atcute/client": ["@atcute/client@4.0.5", "", { "dependencies": { "@atcute/identity": "^1.1.1", "@atcute/lexicons": "^1.2.2" } }, "sha512-R8Qen8goGmEkynYGg2m6XFlVmz0GTDvQ+9w+4QqOob+XMk8/WDpF4aImev7WKEde/rV2gjcqW7zM8E6W9NShDA=="],
-
"@atcute/identity": ["@atcute/identity@1.1.1", "", { "dependencies": { "@atcute/lexicons": "^1.2.2", "@badrap/valita": "^0.4.6" } }, "sha512-zax42n693VEhnC+5tndvO2KLDTMkHOz8UExwmklvJv7R9VujfEwiSWhcv6Jgwb3ellaG8wjiQ1lMOIjLLvwh0Q=="],
+
"@atcute/identity": ["@atcute/identity@1.1.2", "", { "dependencies": { "@atcute/lexicons": "^1.2.3", "@badrap/valita": "^0.4.6" } }, "sha512-vn0RN7SUF6N0sEPG9yyT6a0MzpfVS8BhsiLtB8OeS4qp2rLMQW33pelCpNitP1N+fq03MFlDGzs5p7K4qMs4cA=="],
"@atcute/identity-resolver": ["@atcute/identity-resolver@1.1.4", "", { "dependencies": { "@atcute/lexicons": "^1.2.2", "@atcute/util-fetch": "^1.0.3", "@badrap/valita": "^0.4.6" }, "peerDependencies": { "@atcute/identity": "^1.0.0" } }, "sha512-/SVh8vf2cXFJenmBnGeYF2aY3WGQm3cJeew5NWTlkqoy3LvJ5wkvKq9PWu4Tv653VF40rPOp6LOdVr9Fa+q5rA=="],
-
"@atcute/lexicons": ["@atcute/lexicons@1.2.2", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "esm-env": "^1.2.2" } }, "sha512-bgEhJq5Z70/0TbK5sx+tAkrR8FsCODNiL2gUEvS5PuJfPxmFmRYNWaMGehxSPaXWpU2+Oa9ckceHiYbrItDTkA=="],
+
"@atcute/lexicons": ["@atcute/lexicons@1.2.3", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "esm-env": "^1.2.2" } }, "sha512-ZNfNWS4jaR8VgWSSBaWRSSmwFeP134BmvpTt9JmM2x5vRoXeIFthxU9USY8ZV4vm0GPoxEMgkDin8HIlnFTg2w=="],
+
+
"@atcute/microcosm": ["@atcute/microcosm@1.0.0", "", { "dependencies": { "@atcute/lexicons": "^1.2.3" } }, "sha512-XJW+TMvdktH2maTkVcNU6wKmnHpmNwhmg0Xj4ZY36plHpqNHfxR4kAAcXGSJcjH9CS8I1+cTHiyUQykdeOPeGg=="],
"@atcute/multibase": ["@atcute/multibase@1.1.6", "", { "dependencies": { "@atcute/uint8array": "^1.0.5" } }, "sha512-HBxuCgYLKPPxETV0Rot4VP9e24vKl8JdzGCZOVsDaOXJgbRZoRIF67Lp0H/OgnJeH/Xpva8Z5ReoTNJE5dn3kg=="],
"@atcute/oauth-browser-client": ["@atcute/oauth-browser-client@2.0.1", "", { "dependencies": { "@atcute/client": "^4.0.5", "@atcute/identity": "^1.1.1", "@atcute/identity-resolver": "^1.1.4", "@atcute/lexicons": "^1.2.2", "@atcute/multibase": "^1.1.6", "@atcute/uint8array": "^1.0.5", "nanoid": "^5.1.5" } }, "sha512-lG021GkeORG06zfFf4bH85egObjBEKHNgAWHvbtY/E2dX4wxo88hf370pJDx8acdnuUJLJ2VKPikJtZwo4Heeg=="],
-
"@atcute/tangled": ["@atcute/tangled@1.0.10", "", { "dependencies": { "@atcute/atproto": "^3.1.8", "@atcute/lexicons": "^1.2.2" } }, "sha512-DGconZIN5TpLBah+aHGbWI1tMsL7XzyVEbr/fW4CbcLWYKICU6SAUZ0YnZ+5GvltjlORWHUy7hfftvoh4zodIA=="],
+
"@atcute/tangled": ["@atcute/tangled@1.0.12", "", { "dependencies": { "@atcute/atproto": "^3.1.9", "@atcute/lexicons": "^1.2.3" } }, "sha512-JKA5sOhd8SLhDFhY+PKHqLLytQBBKSiwcaEzfYUJBeyfvqXFPNNAwvRbe3VST4IQ3izoOu3O0R9/b1mjL45UzA=="],
"@atcute/uint8array": ["@atcute/uint8array@1.0.5", "", {}, "sha512-XLWWxoR2HNl2qU+FCr0rp1APwJXci7HnzbOQLxK55OaMNBXZ19+xNC5ii4QCsThsDxa4JS/JTzuiQLziITWf2Q=="],
"@atcute/util-fetch": ["@atcute/util-fetch@1.0.3", "", { "dependencies": { "@badrap/valita": "^0.4.6" } }, "sha512-f8zzTb/xlKIwv2OQ31DhShPUNCmIIleX6p7qIXwWwEUjX6x8skUtpdISSjnImq01LXpltGV5y8yhV4/Mlb7CRQ=="],
-
"@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "7.27.1", "js-tokens": "4.0.0", "picocolors": "1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="],
+
"@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="],
-
"@babel/compat-data": ["@babel/compat-data@7.28.4", "", {}, "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw=="],
+
"@babel/compat-data": ["@babel/compat-data@7.28.5", "", {}, "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA=="],
-
"@babel/core": ["@babel/core@7.28.4", "", { "dependencies": { "@babel/code-frame": "7.27.1", "@babel/generator": "7.28.3", "@babel/helper-compilation-targets": "7.27.2", "@babel/helper-module-transforms": "7.28.3", "@babel/helpers": "7.28.4", "@babel/parser": "7.28.4", "@babel/template": "7.27.2", "@babel/traverse": "7.28.4", "@babel/types": "7.28.4", "@jridgewell/remapping": "2.3.5", "convert-source-map": "2.0.0", "debug": "4.4.3", "gensync": "1.0.0-beta.2", "json5": "2.2.3", "semver": "6.3.1" } }, "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA=="],
+
"@babel/core": ["@babel/core@7.28.5", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", "@babel/helpers": "^7.28.4", "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw=="],
-
"@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "7.28.4", "@babel/types": "7.28.4", "@jridgewell/gen-mapping": "0.3.13", "@jridgewell/trace-mapping": "0.3.31", "jsesc": "3.1.0" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="],
+
"@babel/generator": ["@babel/generator@7.28.5", "", { "dependencies": { "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ=="],
-
"@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.2", "", { "dependencies": { "@babel/compat-data": "7.28.4", "@babel/helper-validator-option": "7.27.1", "browserslist": "4.26.3", "lru-cache": "5.1.1", "semver": "6.3.1" } }, "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ=="],
+
"@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.2", "", { "dependencies": { "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ=="],
"@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],
-
"@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "7.28.4", "@babel/types": "7.28.4" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="],
+
"@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="],
-
"@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.3", "", { "dependencies": { "@babel/helper-module-imports": "7.27.1", "@babel/helper-validator-identifier": "7.27.1", "@babel/traverse": "7.28.4" }, "peerDependencies": { "@babel/core": "7.28.4" } }, "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw=="],
+
"@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.3", "", { "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", "@babel/traverse": "^7.28.3" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw=="],
"@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.27.1", "", {}, "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw=="],
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
-
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="],
+
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
"@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
-
"@babel/helpers": ["@babel/helpers@7.28.4", "", { "dependencies": { "@babel/template": "7.27.2", "@babel/types": "7.28.4" } }, "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w=="],
+
"@babel/helpers": ["@babel/helpers@7.28.4", "", { "dependencies": { "@babel/template": "^7.27.2", "@babel/types": "^7.28.4" } }, "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w=="],
-
"@babel/parser": ["@babel/parser@7.28.4", "", { "dependencies": { "@babel/types": "7.28.4" }, "bin": "./bin/babel-parser.js" }, "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg=="],
+
"@babel/parser": ["@babel/parser@7.28.5", "", { "dependencies": { "@babel/types": "^7.28.5" }, "bin": "./bin/babel-parser.js" }, "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ=="],
-
"@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "7.27.1" }, "peerDependencies": { "@babel/core": "7.28.4" } }, "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w=="],
+
"@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w=="],
-
"@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "7.27.1" }, "peerDependencies": { "@babel/core": "7.28.4" } }, "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ=="],
+
"@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ=="],
-
"@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "7.27.1", "@babel/parser": "7.28.4", "@babel/types": "7.28.4" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="],
+
"@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="],
-
"@babel/traverse": ["@babel/traverse@7.28.4", "", { "dependencies": { "@babel/code-frame": "7.27.1", "@babel/generator": "7.28.3", "@babel/helper-globals": "7.28.0", "@babel/parser": "7.28.4", "@babel/template": "7.27.2", "@babel/types": "7.28.4", "debug": "4.4.3" } }, "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ=="],
+
"@babel/traverse": ["@babel/traverse@7.28.5", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", "@babel/types": "^7.28.5", "debug": "^4.3.1" } }, "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ=="],
-
"@babel/types": ["@babel/types@7.28.4", "", { "dependencies": { "@babel/helper-string-parser": "7.27.1", "@babel/helper-validator-identifier": "7.27.1" } }, "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q=="],
+
"@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="],
"@badrap/valita": ["@badrap/valita@0.4.6", "", {}, "sha512-4kdqcjyxo/8RQ8ayjms47HCWZIF5981oE5nIenbfThKDxWXtEHKipAOWlflpPJzZx9y/JWYQkp18Awr7VuepFg=="],
-
"@biomejs/biome": ["@biomejs/biome@2.3.4", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.4", "@biomejs/cli-darwin-x64": "2.3.4", "@biomejs/cli-linux-arm64": "2.3.4", "@biomejs/cli-linux-arm64-musl": "2.3.4", "@biomejs/cli-linux-x64": "2.3.4", "@biomejs/cli-linux-x64-musl": "2.3.4", "@biomejs/cli-win32-arm64": "2.3.4", "@biomejs/cli-win32-x64": "2.3.4" }, "bin": { "biome": "bin/biome" } }, "sha512-TU08LXjBHdy0mEY9APtEtZdNQQijXUDSXR7IK1i45wgoPD5R0muK7s61QcFir6FpOj/RP1+YkPx5QJlycXUU3w=="],
+
"@biomejs/biome": ["@biomejs/biome@2.3.6", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.6", "@biomejs/cli-darwin-x64": "2.3.6", "@biomejs/cli-linux-arm64": "2.3.6", "@biomejs/cli-linux-arm64-musl": "2.3.6", "@biomejs/cli-linux-x64": "2.3.6", "@biomejs/cli-linux-x64-musl": "2.3.6", "@biomejs/cli-win32-arm64": "2.3.6", "@biomejs/cli-win32-x64": "2.3.6" }, "bin": { "biome": "bin/biome" } }, "sha512-oqUhWyU6tae0MFsr/7iLe++QWRg+6jtUhlx9/0GmCWDYFFrK366sBLamNM7D9Y+c7YSynUFKr8lpEp1r6Sk7eA=="],
-
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-w40GvlNzLaqmuWYiDU6Ys9FNhJiclngKqcGld3iJIiy2bpJ0Q+8n3haiaC81uTPY/NA0d8Q/I3Z9+ajc14102Q=="],
+
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-P4JWE5d8UayBxYe197QJwyW4ZHp0B+zvRIGCusOm1WbxmlhpAQA1zEqQuunHgSIzvyEEp4TVxiKGXNFZPg7r9Q=="],
-
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.3.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-3s7TLVtjJ7ni1xADXsS7x7GMUrLBZXg8SemXc3T0XLslzvqKj/dq1xGeBQ+pOWQzng9MaozfacIHdK2UlJ3jGA=="],
+
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.3.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-I4rTebj+F/L9K93IU7yTFs8nQ6EhaCOivxduRha4w4WEZK80yoZ8OAdR1F33m4yJ/NfUuTUbP/Wjs+vKjlCoWA=="],
-
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.3.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-y7efHyyM2gYmHy/AdWEip+VgTMe9973aP7XYKPzu/j8JxnPHuSUXftzmPhkVw0lfm4ECGbdBdGD6+rLmTgNZaA=="],
+
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.3.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-JjYy83eVBnvuINZiqyFO7xx72v8Srh4hsgaacSBCjC22DwM6+ZvnX1/fj8/SBiLuUOfZ8YhU2pfq2Dzakeyg1A=="],
-
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.3.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-IruVGQRwMURivWazchiq7gKAqZSFs5so6gi0hJyxk7x6HR+iwZbO2IxNOqyLURBvL06qkIHs7Wffl6Bw30vCbQ=="],
+
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.3.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-oK1NpIXIixbJ/4Tcx40cwiieqah6rRUtMGOHDeK2ToT7yUFVEvXUGRKqH0O4hqZ9tW8TcXNZKfgRH6xrsjVtGg=="],
-
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.3.4", "", { "os": "linux", "cpu": "x64" }, "sha512-gKfjWR/6/dfIxPJCw8REdEowiXCkIpl9jycpNVHux8aX2yhWPLjydOshkDL6Y/82PcQJHn95VCj7J+BRcE5o1Q=="],
+
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.3.6", "", { "os": "linux", "cpu": "x64" }, "sha512-ZjPXzy5yN9wusIoX+8Zp4p6cL8r0NzJCXg/4r1KLVveIPXd2jKVlqZ6ZyzEq385WwU3OX5KOwQYLQsOc788waQ=="],
-
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.3.4", "", { "os": "linux", "cpu": "x64" }, "sha512-mzKFFv/w66e4/jCobFmD3kymCqG+FuWE7sVa4Yjqd9v7qt2UhXo67MSZKY9Ih18V2IwPzRKQPCw6KwdZs6AXSA=="],
+
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.3.6", "", { "os": "linux", "cpu": "x64" }, "sha512-QvxB8GHQeaO4FCtwJpJjCgJkbHBbWxRHUxQlod+xeaYE6gtJdSkYkuxdKAQUZEOIsec+PeaDAhW9xjzYbwmOFA=="],
-
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.3.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-5TJ6JfVez+yyupJ/iGUici2wzKf0RrSAxJhghQXtAEsc67OIpdwSKAQboemILrwKfHDi5s6mu7mX+VTCTUydkw=="],
+
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.3.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-YM7hLHpwjdt8R7+O2zS1Vo2cKgqEeptiXB1tWW1rgjN5LlpZovBVKtg7zfwfRrFx3i08aNZThYpTcowpTlczug=="],
-
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.4", "", { "os": "win32", "cpu": "x64" }, "sha512-FGCijXecmC4IedQ0esdYNlMpx0Jxgf4zceCaMu6fkjWyjgn50ZQtMiqZZQ0Q/77yqPxvtkgZAvt5uGw0gAAjig=="],
+
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.6", "", { "os": "win32", "cpu": "x64" }, "sha512-psgNEYgMAobY5h+QHRBVR9xvg2KocFuBKm6axZWB/aD12NWhQjiVFQUjV6wMXhlH4iT0Q9c3yK5JFRiDC/rzHA=="],
-
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.11", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg=="],
+
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="],
-
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.11", "", { "os": "android", "cpu": "arm" }, "sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg=="],
+
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="],
-
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.11", "", { "os": "android", "cpu": "arm64" }, "sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ=="],
+
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="],
-
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.11", "", { "os": "android", "cpu": "x64" }, "sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g=="],
+
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="],
-
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w=="],
+
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="],
-
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ=="],
+
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="],
-
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.11", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA=="],
+
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="],
-
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.11", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw=="],
+
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="],
-
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.11", "", { "os": "linux", "cpu": "arm" }, "sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw=="],
+
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="],
-
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA=="],
+
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="],
-
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.11", "", { "os": "linux", "cpu": "ia32" }, "sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw=="],
+
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="],
-
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw=="],
+
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="],
-
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ=="],
+
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="],
-
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.11", "", { "os": "linux", "cpu": "ppc64" }, "sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw=="],
+
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="],
-
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww=="],
+
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="],
-
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.11", "", { "os": "linux", "cpu": "s390x" }, "sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw=="],
+
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="],
-
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.11", "", { "os": "linux", "cpu": "x64" }, "sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ=="],
+
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="],
-
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.11", "", { "os": "none", "cpu": "arm64" }, "sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg=="],
+
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="],
-
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.11", "", { "os": "none", "cpu": "x64" }, "sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A=="],
+
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="],
-
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.11", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg=="],
+
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="],
-
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.11", "", { "os": "openbsd", "cpu": "x64" }, "sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw=="],
+
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="],
-
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.11", "", { "os": "none", "cpu": "arm64" }, "sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ=="],
+
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="],
-
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.11", "", { "os": "sunos", "cpu": "x64" }, "sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA=="],
+
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="],
-
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q=="],
+
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="],
-
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.11", "", { "os": "win32", "cpu": "ia32" }, "sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA=="],
+
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="],
-
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.11", "", { "os": "win32", "cpu": "x64" }, "sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA=="],
+
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="],
"@gleam-lang/highlight.js-gleam": ["@gleam-lang/highlight.js-gleam@1.5.0", "", {}, "sha512-rKKpXnfmHVTPuHEogMVvN4DflzKtX6kBXqu1GsVDb0uDf/bvO8Z2VnC0XWUMuKNlxa+poKIjY6geyxTaVZiMFA=="],
···
"@iconify/utils": ["@iconify/utils@2.3.0", "", { "dependencies": { "@antfu/install-pkg": "^1.0.0", "@antfu/utils": "^8.1.0", "@iconify/types": "^2.0.0", "debug": "^4.4.0", "globals": "^15.14.0", "kolorist": "^1.8.0", "local-pkg": "^1.0.0", "mlly": "^1.7.4" } }, "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA=="],
-
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "1.5.5", "@jridgewell/trace-mapping": "0.3.30" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
+
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
-
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "0.3.13", "@jridgewell/trace-mapping": "0.3.30" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
+
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
-
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "3.1.2", "@jridgewell/sourcemap-codec": "1.5.5" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
+
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
"@nothing-but/utils": ["@nothing-but/utils@0.17.0", "", {}, "sha512-TuCHcHLOqDL0SnaAxACfuRHBNRgNJcNn9X0GiH5H3YSDBVquCr3qEIG3FOQAuMyZCbu9w8nk2CHhOsn7IvhIwQ=="],
-
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.5", "", { "os": "android", "cpu": "arm" }, "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ=="],
+
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.53.3", "", { "os": "android", "cpu": "arm" }, "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w=="],
-
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.52.5", "", { "os": "android", "cpu": "arm64" }, "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA=="],
+
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.53.3", "", { "os": "android", "cpu": "arm64" }, "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w=="],
-
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.52.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA=="],
+
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.53.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA=="],
-
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.52.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA=="],
+
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.53.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ=="],
-
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.52.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA=="],
+
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.53.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w=="],
-
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.52.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ=="],
+
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.53.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q=="],
-
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ=="],
+
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.53.3", "", { "os": "linux", "cpu": "arm" }, "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw=="],
-
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ=="],
+
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.53.3", "", { "os": "linux", "cpu": "arm" }, "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg=="],
-
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg=="],
+
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.53.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w=="],
-
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q=="],
+
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.53.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A=="],
-
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA=="],
+
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.53.3", "", { "os": "linux", "cpu": "none" }, "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g=="],
-
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.52.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw=="],
+
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.53.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw=="],
-
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw=="],
+
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.53.3", "", { "os": "linux", "cpu": "none" }, "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g=="],
-
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg=="],
+
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.53.3", "", { "os": "linux", "cpu": "none" }, "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A=="],
-
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.52.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ=="],
+
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.53.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg=="],
-
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q=="],
+
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.53.3", "", { "os": "linux", "cpu": "x64" }, "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w=="],
-
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg=="],
+
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.53.3", "", { "os": "linux", "cpu": "x64" }, "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q=="],
-
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.52.5", "", { "os": "none", "cpu": "arm64" }, "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw=="],
+
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.53.3", "", { "os": "none", "cpu": "arm64" }, "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw=="],
-
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.52.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w=="],
+
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.53.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw=="],
-
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.52.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg=="],
+
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.53.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA=="],
-
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ=="],
+
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.53.3", "", { "os": "win32", "cpu": "x64" }, "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg=="],
-
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg=="],
+
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.53.3", "", { "os": "win32", "cpu": "x64" }, "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ=="],
-
"@solid-devtools/debugger": ["@solid-devtools/debugger@0.28.1", "", { "dependencies": { "@nothing-but/utils": "0.17.0", "@solid-devtools/shared": "0.20.0", "@solid-primitives/bounds": "0.1.3", "@solid-primitives/event-listener": "2.4.3", "@solid-primitives/keyboard": "1.3.3", "@solid-primitives/rootless": "1.5.2", "@solid-primitives/scheduled": "1.5.2", "@solid-primitives/static-store": "0.1.2", "@solid-primitives/utils": "6.3.2" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-6qIUI6VYkXoRnL8oF5bvh2KgH71qlJ18hNw/mwSyY6v48eb80ZR48/5PDXufUa3q+MBSuYa1uqTMwLewpay9eg=="],
+
"@solid-devtools/debugger": ["@solid-devtools/debugger@0.28.1", "", { "dependencies": { "@nothing-but/utils": "~0.17.0", "@solid-devtools/shared": "^0.20.0", "@solid-primitives/bounds": "^0.1.1", "@solid-primitives/event-listener": "^2.4.1", "@solid-primitives/keyboard": "^1.3.1", "@solid-primitives/rootless": "^1.5.1", "@solid-primitives/scheduled": "^1.5.1", "@solid-primitives/static-store": "^0.1.1", "@solid-primitives/utils": "^6.3.1" }, "peerDependencies": { "solid-js": "^1.9.0" } }, "sha512-6qIUI6VYkXoRnL8oF5bvh2KgH71qlJ18hNw/mwSyY6v48eb80ZR48/5PDXufUa3q+MBSuYa1uqTMwLewpay9eg=="],
-
"@solid-devtools/shared": ["@solid-devtools/shared@0.20.0", "", { "dependencies": { "@nothing-but/utils": "0.17.0", "@solid-primitives/event-listener": "2.4.3", "@solid-primitives/media": "2.3.3", "@solid-primitives/refs": "1.1.2", "@solid-primitives/rootless": "1.5.2", "@solid-primitives/scheduled": "1.5.2", "@solid-primitives/static-store": "0.1.2", "@solid-primitives/styles": "0.1.2", "@solid-primitives/utils": "6.3.2" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-o5TACmUOQsxpzpOKCjbQqGk8wL8PMi+frXG9WNu4Lh3PQVUB6hs95Kl/S8xc++zwcMguUKZJn8h5URUiMOca6Q=="],
+
"@solid-devtools/shared": ["@solid-devtools/shared@0.20.0", "", { "dependencies": { "@nothing-but/utils": "~0.17.0", "@solid-primitives/event-listener": "^2.4.1", "@solid-primitives/media": "^2.3.1", "@solid-primitives/refs": "^1.1.1", "@solid-primitives/rootless": "^1.5.1", "@solid-primitives/scheduled": "^1.5.1", "@solid-primitives/static-store": "^0.1.1", "@solid-primitives/styles": "^0.1.1", "@solid-primitives/utils": "^6.3.1" }, "peerDependencies": { "solid-js": "^1.9.0" } }, "sha512-o5TACmUOQsxpzpOKCjbQqGk8wL8PMi+frXG9WNu4Lh3PQVUB6hs95Kl/S8xc++zwcMguUKZJn8h5URUiMOca6Q=="],
-
"@solid-primitives/bounds": ["@solid-primitives/bounds@0.1.3", "", { "dependencies": { "@solid-primitives/event-listener": "2.4.3", "@solid-primitives/resize-observer": "2.1.3", "@solid-primitives/static-store": "0.1.2", "@solid-primitives/utils": "6.3.2" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-UbiyKMdSPmtijcEDnYLQL3zzaejpwWDAJJ4Gt5P0hgVs6A72piov0GyNw7V2SroH7NZFwxlYS22YmOr8A5xc1Q=="],
+
"@solid-primitives/bounds": ["@solid-primitives/bounds@0.1.3", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.3", "@solid-primitives/resize-observer": "^2.1.3", "@solid-primitives/static-store": "^0.1.2", "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-UbiyKMdSPmtijcEDnYLQL3zzaejpwWDAJJ4Gt5P0hgVs6A72piov0GyNw7V2SroH7NZFwxlYS22YmOr8A5xc1Q=="],
-
"@solid-primitives/event-listener": ["@solid-primitives/event-listener@2.4.3", "", { "dependencies": { "@solid-primitives/utils": "6.3.2" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-h4VqkYFv6Gf+L7SQj+Y6puigL/5DIi7x5q07VZET7AWcS+9/G3WfIE9WheniHWJs51OEkRB43w6lDys5YeFceg=="],
+
"@solid-primitives/event-listener": ["@solid-primitives/event-listener@2.4.3", "", { "dependencies": { "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-h4VqkYFv6Gf+L7SQj+Y6puigL/5DIi7x5q07VZET7AWcS+9/G3WfIE9WheniHWJs51OEkRB43w6lDys5YeFceg=="],
-
"@solid-primitives/keyboard": ["@solid-primitives/keyboard@1.3.3", "", { "dependencies": { "@solid-primitives/event-listener": "2.4.3", "@solid-primitives/rootless": "1.5.2", "@solid-primitives/utils": "6.3.2" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-9dQHTTgLBqyAI7aavtO+HnpTVJgWQA1ghBSrmLtMu1SMxLPDuLfuNr+Tk5udb4AL4Ojg7h9JrKOGEEDqsJXWJA=="],
+
"@solid-primitives/keyboard": ["@solid-primitives/keyboard@1.3.3", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.3", "@solid-primitives/rootless": "^1.5.2", "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-9dQHTTgLBqyAI7aavtO+HnpTVJgWQA1ghBSrmLtMu1SMxLPDuLfuNr+Tk5udb4AL4Ojg7h9JrKOGEEDqsJXWJA=="],
-
"@solid-primitives/media": ["@solid-primitives/media@2.3.3", "", { "dependencies": { "@solid-primitives/event-listener": "2.4.3", "@solid-primitives/rootless": "1.5.2", "@solid-primitives/static-store": "0.1.2", "@solid-primitives/utils": "6.3.2" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-hQ4hLOGvfbugQi5Eu1BFWAIJGIAzztq9x0h02xgBGl2l0Jaa3h7tg6bz5tV1NSuNYVGio4rPoa7zVQQLkkx9dA=="],
+
"@solid-primitives/media": ["@solid-primitives/media@2.3.3", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.3", "@solid-primitives/rootless": "^1.5.2", "@solid-primitives/static-store": "^0.1.2", "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-hQ4hLOGvfbugQi5Eu1BFWAIJGIAzztq9x0h02xgBGl2l0Jaa3h7tg6bz5tV1NSuNYVGio4rPoa7zVQQLkkx9dA=="],
-
"@solid-primitives/refs": ["@solid-primitives/refs@1.1.2", "", { "dependencies": { "@solid-primitives/utils": "6.3.2" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-K7tf2thy7L+YJjdqXspXOg5xvNEOH8tgEWsp0+1mQk3obHBRD6hEjYZk7p7FlJphSZImS35je3UfmWuD7MhDfg=="],
+
"@solid-primitives/refs": ["@solid-primitives/refs@1.1.2", "", { "dependencies": { "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-K7tf2thy7L+YJjdqXspXOg5xvNEOH8tgEWsp0+1mQk3obHBRD6hEjYZk7p7FlJphSZImS35je3UfmWuD7MhDfg=="],
-
"@solid-primitives/resize-observer": ["@solid-primitives/resize-observer@2.1.3", "", { "dependencies": { "@solid-primitives/event-listener": "2.4.3", "@solid-primitives/rootless": "1.5.2", "@solid-primitives/static-store": "0.1.2", "@solid-primitives/utils": "6.3.2" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-zBLje5E06TgOg93S7rGPldmhDnouNGhvfZVKOp+oG2XU8snA+GoCSSCz1M+jpNAg5Ek2EakU5UVQqL152WmdXQ=="],
+
"@solid-primitives/resize-observer": ["@solid-primitives/resize-observer@2.1.3", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.3", "@solid-primitives/rootless": "^1.5.2", "@solid-primitives/static-store": "^0.1.2", "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-zBLje5E06TgOg93S7rGPldmhDnouNGhvfZVKOp+oG2XU8snA+GoCSSCz1M+jpNAg5Ek2EakU5UVQqL152WmdXQ=="],
-
"@solid-primitives/rootless": ["@solid-primitives/rootless@1.5.2", "", { "dependencies": { "@solid-primitives/utils": "6.3.2" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-9HULb0QAzL2r47CCad0M+NKFtQ+LrGGNHZfteX/ThdGvKIg2o2GYhBooZubTCd/RTu2l2+Nw4s+dEfiDGvdrrQ=="],
+
"@solid-primitives/rootless": ["@solid-primitives/rootless@1.5.2", "", { "dependencies": { "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-9HULb0QAzL2r47CCad0M+NKFtQ+LrGGNHZfteX/ThdGvKIg2o2GYhBooZubTCd/RTu2l2+Nw4s+dEfiDGvdrrQ=="],
-
"@solid-primitives/scheduled": ["@solid-primitives/scheduled@1.5.2", "", { "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-/j2igE0xyNaHhj6kMfcUQn5rAVSTLbAX+CDEBm25hSNBmNiHLu2lM7Usj2kJJ5j36D67bE8wR1hBNA8hjtvsQA=="],
+
"@solid-primitives/scheduled": ["@solid-primitives/scheduled@1.5.2", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-/j2igE0xyNaHhj6kMfcUQn5rAVSTLbAX+CDEBm25hSNBmNiHLu2lM7Usj2kJJ5j36D67bE8wR1hBNA8hjtvsQA=="],
-
"@solid-primitives/static-store": ["@solid-primitives/static-store@0.1.2", "", { "dependencies": { "@solid-primitives/utils": "6.3.2" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-ReK+5O38lJ7fT+L6mUFvUr6igFwHBESZF+2Ug842s7fvlVeBdIVEdTCErygff6w7uR6+jrr7J8jQo+cYrEq4Iw=="],
+
"@solid-primitives/static-store": ["@solid-primitives/static-store@0.1.2", "", { "dependencies": { "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-ReK+5O38lJ7fT+L6mUFvUr6igFwHBESZF+2Ug842s7fvlVeBdIVEdTCErygff6w7uR6+jrr7J8jQo+cYrEq4Iw=="],
-
"@solid-primitives/styles": ["@solid-primitives/styles@0.1.2", "", { "dependencies": { "@solid-primitives/rootless": "1.5.2", "@solid-primitives/utils": "6.3.2" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-7iX5K+J5b1PRrbgw3Ki92uvU2LgQ0Kd/QMsrAZxDg5dpUBwMyTijZkA3bbs1ikZsT1oQhS41bTyKbjrXeU0Awg=="],
+
"@solid-primitives/styles": ["@solid-primitives/styles@0.1.2", "", { "dependencies": { "@solid-primitives/rootless": "^1.5.2", "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-7iX5K+J5b1PRrbgw3Ki92uvU2LgQ0Kd/QMsrAZxDg5dpUBwMyTijZkA3bbs1ikZsT1oQhS41bTyKbjrXeU0Awg=="],
-
"@solid-primitives/utils": ["@solid-primitives/utils@6.3.2", "", { "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-hZ/M/qr25QOCcwDPOHtGjxTD8w2mNyVAYvcfgwzBHq2RwNqHNdDNsMZYap20+ruRwW4A3Cdkczyoz0TSxLCAPQ=="],
+
"@solid-primitives/utils": ["@solid-primitives/utils@6.3.2", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-hZ/M/qr25QOCcwDPOHtGjxTD8w2mNyVAYvcfgwzBHq2RwNqHNdDNsMZYap20+ruRwW4A3Cdkczyoz0TSxLCAPQ=="],
-
"@solidjs/router": ["@solidjs/router@0.15.3", "", { "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-iEbW8UKok2Oio7o6Y4VTzLj+KFCmQPGEpm1fS3xixwFBdclFVBvaQVeibl1jys4cujfAK5Kn6+uG2uBm3lxOMw=="],
+
"@solidjs/router": ["@solidjs/router@0.15.4", "", { "peerDependencies": { "solid-js": "^1.8.6" } }, "sha512-WOpgg9a9T638cR+5FGbFi/IV4l2FpmBs1GpIMSPa0Ce9vyJN7Wts+X2PqMf9IYn0zUj2MlSJtm1gp7/HI/n5TQ=="],
"@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="],
···
"@trysound/sax": ["@trysound/sax@0.2.0", "", {}, "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA=="],
-
"@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "7.28.4", "@babel/types": "7.28.4", "@types/babel__generator": "7.27.0", "@types/babel__template": "7.4.4", "@types/babel__traverse": "7.28.0" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
+
"@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
-
"@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "7.28.4" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
+
"@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
-
"@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "7.28.4", "@babel/types": "7.28.4" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="],
+
"@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="],
-
"@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "7.28.4" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
+
"@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
"@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="],
···
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
-
"@types/node": ["@types/node@24.10.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A=="],
+
"@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="],
"@types/tar": ["@types/tar@6.1.13", "", { "dependencies": { "@types/node": "*", "minipass": "^4.0.0" } }, "sha512-IznnlmU5f4WcGTh2ltRu/Ijpmk8wiWXfF0VA4s+HPjHZgvFggk1YaIkbo5krX/zUCzWF8N/l4+W/LNxnvAJ8nw=="],
···
"axios": ["axios@1.13.2", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA=="],
-
"babel-plugin-jsx-dom-expressions": ["babel-plugin-jsx-dom-expressions@0.40.1", "", { "dependencies": { "@babel/helper-module-imports": "7.18.6", "@babel/plugin-syntax-jsx": "7.27.1", "@babel/types": "7.28.4", "html-entities": "2.3.3", "parse5": "7.3.0", "validate-html-nesting": "1.2.3" }, "peerDependencies": { "@babel/core": "7.28.4" } }, "sha512-b4iHuirqK7RgaMzB2Lsl7MqrlDgQtVRSSazyrmx7wB3T759ggGjod5Rkok5MfHjQXhR7tRPmdwoeGPqBnW2KfA=="],
+
"babel-plugin-jsx-dom-expressions": ["babel-plugin-jsx-dom-expressions@0.40.3", "", { "dependencies": { "@babel/helper-module-imports": "7.18.6", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/types": "^7.20.7", "html-entities": "2.3.3", "parse5": "^7.1.2" }, "peerDependencies": { "@babel/core": "^7.20.12" } }, "sha512-5HOwwt0BYiv/zxl7j8Pf2bGL6rDXfV6nUhLs8ygBX+EFJXzBPHM/euj9j/6deMZ6wa52Wb2PBaAV5U/jKwIY1w=="],
-
"babel-preset-solid": ["babel-preset-solid@1.9.9", "", { "dependencies": { "babel-plugin-jsx-dom-expressions": "0.40.1" }, "optionalDependencies": { "solid-js": "1.9.9" }, "peerDependencies": { "@babel/core": "7.28.4" } }, "sha512-pCnxWrciluXCeli/dj5PIEHgbNzim3evtTn12snjqqg8QZWJNMjH1AWIp4iG/tbVjqQ72aBEymMSagvmgxubXw=="],
+
"babel-preset-solid": ["babel-preset-solid@1.9.10", "", { "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.40.3" }, "peerDependencies": { "@babel/core": "^7.0.0", "solid-js": "^1.9.10" }, "optionalPeers": ["solid-js"] }, "sha512-HCelrgua/Y+kqO8RyL04JBWS/cVdrtUv/h45GntgQY+cJl4eBcKkCDV3TdMjtKx1nXwRaR9QXslM/Npm1dxdZQ=="],
"bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="],
-
"baseline-browser-mapping": ["baseline-browser-mapping@2.8.18", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-UYmTpOBwgPScZpS4A+YbapwWuBwasxvO/2IOHArSsAhL/+ZdmATBXTex3t+l2hXwLVYK382ibr/nKoY9GKe86w=="],
+
"baseline-browser-mapping": ["baseline-browser-mapping@2.8.30", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-aTUKW4ptQhS64+v2d6IkPzymEzzhw+G0bA1g3uBRV3+ntkH+svttKseW5IOR4Ed6NUVKqnY7qT3dKvzQ7io4AA=="],
"boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="],
-
"browserslist": ["browserslist@4.26.3", "", { "dependencies": { "baseline-browser-mapping": "2.8.18", "caniuse-lite": "1.0.30001751", "electron-to-chromium": "1.5.237", "node-releases": "2.0.25", "update-browserslist-db": "1.1.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w=="],
+
"browserslist": ["browserslist@4.28.0", "", { "dependencies": { "baseline-browser-mapping": "^2.8.25", "caniuse-lite": "^1.0.30001754", "electron-to-chromium": "^1.5.249", "node-releases": "^2.0.27", "update-browserslist-db": "^1.1.4" }, "bin": { "browserslist": "cli.js" } }, "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ=="],
"buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="],
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
-
"caniuse-lite": ["caniuse-lite@1.0.30001751", "", {}, "sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw=="],
+
"caniuse-lite": ["caniuse-lite@1.0.30001756", "", {}, "sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A=="],
"character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="],
···
"csso": ["csso@5.0.5", "", { "dependencies": { "css-tree": "~2.2.0" } }, "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ=="],
-
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
+
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
-
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
+
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
"decode-named-character-reference": ["decode-named-character-reference@1.2.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q=="],
···
"dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
-
"detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],
+
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
"devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
···
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
-
"electron-to-chromium": ["electron-to-chromium@1.5.237", "", {}, "sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg=="],
+
"electron-to-chromium": ["electron-to-chromium@1.5.258", "", {}, "sha512-rHUggNV5jKQ0sSdWwlaRDkFc3/rRJIVnOSe9yR4zrR07m3ZxhP4N27Hlg8VeJGGYgFTxK5NqDmWI4DSH72vIJg=="],
"encoding-sniffer": ["encoding-sniffer@0.2.1", "", { "dependencies": { "iconv-lite": "^0.6.3", "whatwg-encoding": "^3.1.1" } }, "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw=="],
"end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
-
"enhanced-resolve": ["enhanced-resolve@5.18.3", "", { "dependencies": { "graceful-fs": "4.2.11", "tapable": "2.2.3" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="],
+
"enhanced-resolve": ["enhanced-resolve@5.18.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="],
"entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
···
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
-
"esbuild": ["esbuild@0.25.11", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.11", "@esbuild/android-arm": "0.25.11", "@esbuild/android-arm64": "0.25.11", "@esbuild/android-x64": "0.25.11", "@esbuild/darwin-arm64": "0.25.11", "@esbuild/darwin-x64": "0.25.11", "@esbuild/freebsd-arm64": "0.25.11", "@esbuild/freebsd-x64": "0.25.11", "@esbuild/linux-arm": "0.25.11", "@esbuild/linux-arm64": "0.25.11", "@esbuild/linux-ia32": "0.25.11", "@esbuild/linux-loong64": "0.25.11", "@esbuild/linux-mips64el": "0.25.11", "@esbuild/linux-ppc64": "0.25.11", "@esbuild/linux-riscv64": "0.25.11", "@esbuild/linux-s390x": "0.25.11", "@esbuild/linux-x64": "0.25.11", "@esbuild/netbsd-arm64": "0.25.11", "@esbuild/netbsd-x64": "0.25.11", "@esbuild/openbsd-arm64": "0.25.11", "@esbuild/openbsd-x64": "0.25.11", "@esbuild/openharmony-arm64": "0.25.11", "@esbuild/sunos-x64": "0.25.11", "@esbuild/win32-arm64": "0.25.11", "@esbuild/win32-ia32": "0.25.11", "@esbuild/win32-x64": "0.25.11" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q=="],
+
"esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
"esm-env": ["esm-env@1.2.2", "", {}, "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="],
-
"exsolve": ["exsolve@1.0.7", "", {}, "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw=="],
+
"exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="],
"extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
···
"fd-slicer": ["fd-slicer@1.1.0", "", { "dependencies": { "pend": "~1.2.0" } }, "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g=="],
-
"fdir": ["fdir@6.5.0", "", { "optionalDependencies": { "picomatch": "4.0.3" } }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
+
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
"follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="],
-
"form-data": ["form-data@4.0.4", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow=="],
+
"form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="],
"fs-minipass": ["fs-minipass@2.1.0", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="],
···
"local-pkg": ["local-pkg@0.5.1", "", { "dependencies": { "mlly": "^1.7.3", "pkg-types": "^1.2.1" } }, "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ=="],
-
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "3.1.1" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
+
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
···
"mdn-data": ["mdn-data@2.0.30", "", {}, "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="],
-
"merge-anything": ["merge-anything@5.1.7", "", { "dependencies": { "is-what": "4.1.16" } }, "sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ=="],
+
"merge-anything": ["merge-anything@5.1.7", "", { "dependencies": { "is-what": "^4.1.8" } }, "sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ=="],
"micromark": ["micromark@4.0.2", "", { "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA=="],
···
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
-
"node-releases": ["node-releases@2.0.25", "", {}, "sha512-4auku8B/vw5psvTiiN9j1dAOsXvMoGqJuKJcR+dTdqiXEK20mMTk1UEo3HS16LeGQsVG6+qKTPM9u/qQ2LqATA=="],
+
"node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="],
"nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="],
···
"package-manager-detector": ["package-manager-detector@1.5.0", "", {}, "sha512-uBj69dVlYe/+wxj8JOpr97XfsxH/eumMt6HqjNTmJDf/6NO9s+0uxeOneIz3AsPt2m6y9PqzDzd3ATcU17MNfw=="],
-
"parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "6.0.1" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],
+
"parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],
"parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@7.1.0", "", { "dependencies": { "domhandler": "^5.0.3", "parse5": "^7.0.0" } }, "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g=="],
···
"pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
-
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "3.3.11", "picocolors": "1.1.1", "source-map-js": "1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
+
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
"property-information": ["property-information@6.5.0", "", {}, "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig=="],
···
"remark-rehype": ["remark-rehype@11.1.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "mdast-util-to-hast": "^13.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw=="],
-
"rollup": ["rollup@4.52.5", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.5", "@rollup/rollup-android-arm64": "4.52.5", "@rollup/rollup-darwin-arm64": "4.52.5", "@rollup/rollup-darwin-x64": "4.52.5", "@rollup/rollup-freebsd-arm64": "4.52.5", "@rollup/rollup-freebsd-x64": "4.52.5", "@rollup/rollup-linux-arm-gnueabihf": "4.52.5", "@rollup/rollup-linux-arm-musleabihf": "4.52.5", "@rollup/rollup-linux-arm64-gnu": "4.52.5", "@rollup/rollup-linux-arm64-musl": "4.52.5", "@rollup/rollup-linux-loong64-gnu": "4.52.5", "@rollup/rollup-linux-ppc64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-musl": "4.52.5", "@rollup/rollup-linux-s390x-gnu": "4.52.5", "@rollup/rollup-linux-x64-gnu": "4.52.5", "@rollup/rollup-linux-x64-musl": "4.52.5", "@rollup/rollup-openharmony-arm64": "4.52.5", "@rollup/rollup-win32-arm64-msvc": "4.52.5", "@rollup/rollup-win32-ia32-msvc": "4.52.5", "@rollup/rollup-win32-x64-gnu": "4.52.5", "@rollup/rollup-win32-x64-msvc": "4.52.5", "fsevents": "2.3.3" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw=="],
+
"rollup": ["rollup@4.53.3", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.53.3", "@rollup/rollup-android-arm64": "4.53.3", "@rollup/rollup-darwin-arm64": "4.53.3", "@rollup/rollup-darwin-x64": "4.53.3", "@rollup/rollup-freebsd-arm64": "4.53.3", "@rollup/rollup-freebsd-x64": "4.53.3", "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", "@rollup/rollup-linux-arm-musleabihf": "4.53.3", "@rollup/rollup-linux-arm64-gnu": "4.53.3", "@rollup/rollup-linux-arm64-musl": "4.53.3", "@rollup/rollup-linux-loong64-gnu": "4.53.3", "@rollup/rollup-linux-ppc64-gnu": "4.53.3", "@rollup/rollup-linux-riscv64-gnu": "4.53.3", "@rollup/rollup-linux-riscv64-musl": "4.53.3", "@rollup/rollup-linux-s390x-gnu": "4.53.3", "@rollup/rollup-linux-x64-gnu": "4.53.3", "@rollup/rollup-linux-x64-musl": "4.53.3", "@rollup/rollup-openharmony-arm64": "4.53.3", "@rollup/rollup-win32-arm64-msvc": "4.53.3", "@rollup/rollup-win32-ia32-msvc": "4.53.3", "@rollup/rollup-win32-x64-gnu": "4.53.3", "@rollup/rollup-win32-x64-msvc": "4.53.3", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA=="],
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
···
"seroval": ["seroval@1.3.2", "", {}, "sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ=="],
-
"seroval-plugins": ["seroval-plugins@1.3.3", "", { "peerDependencies": { "seroval": "1.3.2" } }, "sha512-16OL3NnUBw8JG1jBLUoZJsLnQq0n5Ua6aHalhJK4fMQkz1lqR7Osz1sA30trBtd9VUDc2NgkuRCn8+/pBwqZ+w=="],
+
"seroval-plugins": ["seroval-plugins@1.3.3", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-16OL3NnUBw8JG1jBLUoZJsLnQq0n5Ua6aHalhJK4fMQkz1lqR7Osz1sA30trBtd9VUDc2NgkuRCn8+/pBwqZ+w=="],
"solid-devtools": ["solid-devtools@0.34.4", "", { "dependencies": { "@babel/core": "^7.27.4", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/types": "^7.27.6", "@solid-devtools/debugger": "^0.28.1", "@solid-devtools/shared": "^0.20.0" }, "peerDependencies": { "solid-js": "^1.9.0", "vite": "^2.2.3 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" }, "optionalPeers": ["vite"] }, "sha512-/s/pPTLvTkuXGZhLfsuvp7ge/cdpEwrUPoRwoJPYgz74GTUSb5Ozi2V6Z6HkO0ILT7hXB04j16HbH1aaP5VFOA=="],
···
"solid-markdown": ["solid-markdown@2.0.14", "", { "dependencies": { "comma-separated-tokens": "^2.0.3", "property-information": "^6.3.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.1", "space-separated-tokens": "^2.0.2", "style-to-object": "^0.3.0", "unified": "^11.0.5", "unist-util-visit": "^4.1.2", "vfile": "^6.0.3" }, "peerDependencies": { "solid-js": "^1.6.0" } }, "sha512-Ln8R4TsNWySXvKkS80OHV+CSR/mwjk5XfGvC5UjZo/y/rAbbkBoxt6FXoWsfCkTW6GH9yxYvahSMXsUJU/ov4Q=="],
-
"solid-refresh": ["solid-refresh@0.6.3", "", { "dependencies": { "@babel/generator": "7.28.3", "@babel/helper-module-imports": "7.27.1", "@babel/types": "7.28.4" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA=="],
+
"solid-refresh": ["solid-refresh@0.6.3", "", { "dependencies": { "@babel/generator": "^7.23.6", "@babel/helper-module-imports": "^7.22.15", "@babel/types": "^7.23.6" }, "peerDependencies": { "solid-js": "^1.3" } }, "sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA=="],
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
···
"tailwindcss": ["tailwindcss@4.1.17", "", {}, "sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q=="],
-
"tapable": ["tapable@2.2.3", "", {}, "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg=="],
+
"tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
"tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="],
"tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="],
-
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "6.5.0", "picomatch": "4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
+
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
"trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="],
···
"unist-util-visit-parents": ["unist-util-visit-parents@5.1.3", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0" } }, "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg=="],
-
"update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "3.2.0", "picocolors": "1.1.1" }, "peerDependencies": { "browserslist": "4.26.3" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="],
-
-
"validate-html-nesting": ["validate-html-nesting@1.2.3", "", {}, "sha512-kdkWdCl6eCeLlRShJKbjVOU2kFKxMF8Ghu50n+crEoyx+VKm3FxAxF9z4DCy6+bbTOqNW0+jcIYRnjoIRzigRw=="],
+
"update-browserslist-db": ["update-browserslist-db@1.1.4", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A=="],
"vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
"vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="],
-
"vite": ["vite@7.2.2", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ=="],
+
"vite": ["vite@7.2.4", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w=="],
"vite-plugin-solid": ["vite-plugin-solid@2.11.10", "", { "dependencies": { "@babel/core": "^7.23.3", "@types/babel__core": "^7.20.4", "babel-preset-solid": "^1.8.4", "merge-anything": "^5.1.7", "solid-refresh": "^0.6.3", "vitefu": "^1.0.4" }, "peerDependencies": { "@testing-library/jest-dom": "^5.16.6 || ^5.17.0 || ^6.*", "solid-js": "^1.7.2", "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" }, "optionalPeers": ["@testing-library/jest-dom"] }, "sha512-Yr1dQybmtDtDAHkii6hXuc1oVH9CPcS/Zb2jN/P36qqcrkNnVPsMTzQ06jyzFPFjj3U1IYKMVt/9ZqcwGCEbjw=="],
-
"vitefu": ["vitefu@1.1.1", "", { "optionalDependencies": { "vite": "7.1.10" } }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="],
+
"vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="],
"whatwg-encoding": ["whatwg-encoding@3.1.1", "", { "dependencies": { "iconv-lite": "0.6.3" } }, "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ=="],
···
"yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
-
"yaml": ["yaml@2.6.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg=="],
-
"yauzl": ["yauzl@2.10.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g=="],
"@atcute/oauth-browser-client/nanoid": ["nanoid@5.1.6", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg=="],
"@iconify/utils/local-pkg": ["local-pkg@1.1.2", "", { "dependencies": { "mlly": "^1.7.4", "pkg-types": "^2.3.0", "quansync": "^0.2.11" } }, "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A=="],
-
"@jridgewell/gen-mapping/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.15" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
+
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.7.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg=="],
-
"@jridgewell/remapping/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.15" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
-
-
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.7.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw=="],
-
-
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.7.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q=="],
+
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.7.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
···
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
-
"babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "7.28.4" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="],
-
-
"babel-preset-solid/solid-js": ["solid-js@1.9.9", "", { "dependencies": { "csstype": "3.1.3", "seroval": "1.3.2", "seroval-plugins": "1.3.3" } }, "sha512-A0ZBPJQldAeGCTW0YRYJmt7RCeh5rbFfPZ2aOttgYnctHE7HgKeHCBB/PVc2P7eOfmNXqMFFFoYYdm3S4dcbkA=="],
+
"babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="],
"csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="],
···
"unist-util-visit-parents/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
-
"vitefu/vite": ["vite@7.1.10", "", { "dependencies": { "esbuild": "0.25.11", "fdir": "6.5.0", "picomatch": "4.0.3", "postcss": "8.5.6", "rollup": "4.52.5", "tinyglobby": "0.2.15" }, "optionalDependencies": { "fsevents": "2.3.3", "jiti": "2.5.1", "lightningcss": "1.30.1", "yaml": "2.6.1" }, "bin": { "vite": "bin/vite.js" } }, "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA=="],
-
"@iconify/utils/local-pkg/pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="],
-
"@jridgewell/gen-mapping/@jridgewell/trace-mapping/@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.0", "", {}, "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w=="],
-
-
"@jridgewell/gen-mapping/@jridgewell/trace-mapping/@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.4.15", "", {}, "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="],
-
-
"@jridgewell/remapping/@jridgewell/trace-mapping/@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.0", "", {}, "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w=="],
-
-
"@jridgewell/remapping/@jridgewell/trace-mapping/@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.4.15", "", {}, "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="],
-
"csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="],
"mdast-util-to-hast/unist-util-visit/unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="],
"mdast-util-to-hast/unist-util-visit/unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="],
-
"vitefu/vite/jiti": ["jiti@2.5.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="],
-
-
"vitefu/vite/lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "2.0.4" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="],
-
"@iconify/utils/local-pkg/pkg-types/confbox": ["confbox@0.2.2", "", {}, "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ=="],
"@iconify/utils/local-pkg/pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
-
-
"vitefu/vite/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="],
-
-
"vitefu/vite/lightningcss/lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA=="],
-
-
"vitefu/vite/lightningcss/lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig=="],
-
-
"vitefu/vite/lightningcss/lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.1", "", { "os": "linux", "cpu": "arm" }, "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q=="],
-
-
"vitefu/vite/lightningcss/lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw=="],
-
-
"vitefu/vite/lightningcss/lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ=="],
-
-
"vitefu/vite/lightningcss/lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw=="],
-
-
"vitefu/vite/lightningcss/lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ=="],
-
-
"vitefu/vite/lightningcss/lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA=="],
-
-
"vitefu/vite/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.1", "", { "os": "win32", "cpu": "x64" }, "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="],
}
}
+43 -40
package.json
···
{
-
"name": "vite-template-solid",
-
"version": "0.0.0",
-
"description": "",
-
"type": "module",
-
"scripts": {
-
"start": "vite",
-
"dev": "vite",
-
"build": "vite build",
-
"serve": "vite preview"
-
},
-
"license": "MIT",
-
"devDependencies": {
-
"@biomejs/biome": "^2.3.4",
-
"@iconify-json/gravity-ui": "^1.2.10",
-
"@iconify/tailwind4": "^1.1.0",
-
"postcss": "^8.5.6",
-
"solid-devtools": "^0.34.4",
-
"tailwindcss": "^4.1.17",
-
"vite": "^7.2.2",
-
"vite-plugin-solid": "^2.11.10"
-
},
-
"dependencies": {
-
"@atcute/atproto": "^3.1.9",
-
"@atcute/client": "^4.0.5",
-
"@atcute/identity-resolver": "^1.1.4",
-
"@atcute/oauth-browser-client": "^2.0.1",
-
"@atcute/tangled": "^1.0.10",
-
"@gleam-lang/highlight.js-gleam": "^1.5.0",
-
"@solidjs/router": "^0.15.3",
-
"@tailwindcss/vite": "^4.1.17",
-
"@types/highlight.js": "^10.1.0",
-
"highlight.js": "^11.11.1",
-
"highlightjs-line-numbers.js": "^2.9.1",
-
"solid-js": "^1.9.10",
-
"solid-markdown": "^2.0.14"
-
},
-
"patchedDependencies": {
-
"@gleam-lang/highlight.js-gleam@1.5.0": "patches/@gleam-lang%2Fhighlight.js-gleam@1.5.0.patch",
-
"highlight.js@11.11.1": "patches/highlight.js@11.11.1.patch"
-
}
+
"name": "vite-template-solid",
+
"version": "0.0.0",
+
"description": "",
+
"type": "module",
+
"scripts": {
+
"start": "vite",
+
"dev": "vite",
+
"build": "vite build",
+
"serve": "vite preview",
+
"lint": "biome lint"
+
},
+
"license": "MIT",
+
"devDependencies": {
+
"@atcute/atproto": "^3.1.9",
+
"@atcute/lexicons": "^1.2.3",
+
"@atcute/microcosm": "^1.0.0",
+
"@atcute/tangled": "^1.0.12",
+
"@biomejs/biome": "^2.3.6",
+
"@iconify-json/gravity-ui": "^1.2.10",
+
"@iconify/tailwind4": "^1.1.0",
+
"postcss": "^8.5.6",
+
"solid-devtools": "^0.34.4",
+
"tailwindcss": "^4.1.17",
+
"vite": "^7.2.4",
+
"vite-plugin-solid": "^2.11.10"
+
},
+
"dependencies": {
+
"@atcute/client": "^4.0.5",
+
"@atcute/identity-resolver": "^1.1.4",
+
"@atcute/oauth-browser-client": "^2.0.1",
+
"@gleam-lang/highlight.js-gleam": "^1.5.0",
+
"@solidjs/router": "^0.15.4",
+
"@tailwindcss/vite": "^4.1.17",
+
"@types/highlight.js": "^10.1.0",
+
"highlight.js": "^11.11.1",
+
"highlightjs-line-numbers.js": "^2.9.1",
+
"solid-js": "^1.9.10",
+
"solid-markdown": "^2.0.14"
+
},
+
"patchedDependencies": {
+
"@gleam-lang/highlight.js-gleam@1.5.0": "patches/@gleam-lang%2Fhighlight.js-gleam@1.5.0.patch",
+
"highlight.js@11.11.1": "patches/highlight.js@11.11.1.patch"
+
}
}
+1 -9
shell.nix
···
{pkgs}:
-
#let
-
# defaultPackage = callPackage ./default.nix { };
-
#in
pkgs.mkShellNoCC {
-
#inputsFrom = [ defaultPackage ];
-
#
-
env = {
-
RUST_SRC_PATH = pkgs.rustPlatform.rustLibSrc;
-
};
-
packages = with pkgs; [
bun
+
nodejs
];
}
+1 -1
src/app.tsx
···
</ul>
</nav>
-
<main class="mt-6 text-gray-950 text-sm dark:text-gray-50">
+
<main class="my-6 text-gray-950 text-sm dark:text-gray-50">
<Suspense>{props.children}</Suspense>
</main>
</>
+32
src/elements/code_block/index.tsx
···
+
import hljs from "highlight.js";
+
import { For } from "solid-js";
+
import "./style.css";
+
import "../../util/highlight.js/index";
+
+
export function CodeBlock(props: { code: string; language: string }) {
+
const highlit = (
+
hljs.getLanguage(props.language)
+
? hljs.highlight(props.code, { language: props.language }).value
+
: props.code
+
).split("\n");
+
const numberSize = highlit.length.toString().length;
+
return (
+
<div class="overflow-x-auto">
+
<div class="flex w-min flex-col whitespace-pre text-nowrap font-mono text-gray-500 dark:text-gray-300">
+
<For each={highlit}>
+
{(line, i) => (
+
<div id={`L${i() + 1}`} class="flex flex-row gap-2">
+
<a
+
href={`#L${i() + 1}`}
+
class="sticky left-0 select-none border-gray-200 border-r bg-white px-1.5 text-gray-500 hover:text-gray-700 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-500 hover:dark:text-gray-200"
+
>
+
{(i() + 1).toString().padStart(numberSize, "โ€‡")}
+
</a>
+
<span innerHTML={line} />
+
</div>
+
)}
+
</For>
+
</div>
+
</div>
+
);
+
}
+73
src/elements/code_block/style.css
···
+
@import "tailwindcss";
+
+
.hljs-operator {
+
@apply text-purple-800 dark:text-purple-300;
+
}
+
+
.hljs-keyword,
+
.hljs-selector-tag,
+
.hljs-meta .hljs-keyword,
+
.hljs-doctag,
+
.hljs-section {
+
@apply text-purple-700 dark:text-purple-400;
+
}
+
+
.hljs-title,
+
.hljs-title.function_ {
+
@apply text-amber-500 dark:text-amber-300;
+
}
+
+
.hljs-attr,
+
.hljs-attribute,
+
.hljs-selector-attr,
+
.hljs-selector-class {
+
@apply text-blue-600 dark:text-blue-400;
+
}
+
+
.hljs-type,
+
.hljs-title.class_,
+
.hljs-title.class_.inherited__,
+
.hljs-template-tag,
+
.hljs-built_in,
+
.hljs-symbol {
+
@apply text-amber-600 dark:text-amber-300;
+
}
+
+
.hljs-string,
+
.hljs-regexp,
+
.hljs-meta .hljs-string {
+
@apply text-green-600 dark:text-green-300;
+
}
+
+
.hljs-number,
+
.hljs-literal,
+
.hljs-bullet,
+
.hljs-code,
+
.hljs-quote {
+
@apply text-orange-600 dark:text-orange-300;
+
}
+
+
.hljs-variable,
+
.hljs-subst {
+
@apply text-gray-800 dark:text-gray-200;
+
}
+
+
.hljs-comment,
+
.hljs-formula,
+
.hljs-meta {
+
@apply italic text-gray-400 dark:text-gray-500;
+
}
+
+
.hljs-emphasis {
+
@apply italic;
+
}
+
.hljs-strong {
+
@apply font-bold;
+
}
+
+
.hljs-addition {
+
@apply bg-green-100 text-green-700 dark:bg-green-800/30 dark:text-green-400;
+
}
+
.hljs-deletion {
+
@apply bg-red-100 text-red-700 dark:bg-red-800/30 dark:text-red-400;
+
}
-31
src/elements/code_block.tsx
···
-
import hljs from "highlight.js";
-
import { createResource, For } from "solid-js";
-
import "../styles/fileviewer.css";
-
import "../util/highlight.js/index";
-
-
export function CodeBlock(props: { code: string; language: string }) {
-
const [codeBlock] = createResource(
-
() => props,
-
(props) => {
-
const highlit = hljs.getLanguage(props.language)
-
? hljs.highlight(props.code, { language: props.language }).value
-
: props.code;
-
return (
-
<For each={highlit.split("\n")}>
-
{(line, i) => (
-
<span class="line-wrapper">
-
<span class="line-number">{i() + 1}</span>
-
<span class="line-content" innerHTML={line}></span>
-
</span>
-
)}
-
</For>
-
);
-
},
-
);
-
-
return (
-
<pre>
-
<code class="flex flex-col text-wrap p-4">{codeBlock()}</code>
-
</pre>
-
);
-
}
-31
src/elements/icon_with_text.tsx
···
-
import { type ComponentProps, splitProps } from "solid-js";
-
import { Dynamic } from "solid-js/web";
-
-
type AllowedTags = "div" | "a" | "span" | "button";
-
-
export function IconWithText<T extends AllowedTags>(
-
props: {
-
type?: T;
-
icon: string;
-
text: string;
-
style?: string;
-
href?: string;
-
} & ComponentProps<T>,
-
) {
-
const [local, dynamic] = splitProps(
-
props,
-
["type", "icon", "text", "style"],
-
["href"],
-
);
-
-
return (
-
<Dynamic
-
component={local.type || "span"}
-
class={`flex flex-row items-center gap-1 ${local.style || ""}`}
-
{...dynamic}
-
>
-
<div class={`iconify ${local.icon}`} />
-
<span>{local.text}</span>
-
</Dynamic>
-
);
-
}
+6 -6
src/errors/404.tsx
···
export default function NotFound() {
-
return (
-
<section class="text-gray-700 p-8">
-
<h1 class="text-2xl font-bold">404: Not Found</h1>
-
<p class="mt-4">It's gone ๐Ÿ˜ž</p>
-
</section>
-
);
+
return (
+
<section class="p-8 text-gray-700">
+
<h1 class="font-bold text-2xl">404: Not Found</h1>
+
<p class="mt-4">It's gone ๐Ÿ˜ž</p>
+
</section>
+
);
}
+13 -3
src/index.tsx
···
import App from "./app";
import NotFound from "./errors/404";
import RepoBlob, { preloadRepoBlob } from "./routes/repo/blob";
-
import RepoCommit from "./routes/repo/commit/commit";
import { RepoProvider } from "./routes/repo/context";
+
import RepoCommit, { preloadRepoCommit } from "./routes/repo/diff/commit";
+
import RepoCompare, { preloadRepoCompare } from "./routes/repo/diff/compare";
import RepoTree, { preloadRepoTree } from "./routes/repo/tree";
import User from "./routes/user";
···
component={RepoBlob}
preload={preloadRepoBlob}
/>
-
<Route path="/commit/:ref" component={RepoCommit} />
-
<Route component={RepoTree} />
+
<Route
+
path="/commit/:ref"
+
component={RepoCommit}
+
preload={preloadRepoCommit}
+
/>
+
<Route
+
path="/compare/:base/:compare"
+
component={RepoCompare}
+
preload={preloadRepoCompare}
+
/>
+
<Route component={RepoTree} preload={preloadRepoTree} />
</Route>
<Route path="/:user" component={User} />
<Route path="*" component={NotFound} />
+78 -15
src/routes/repo/blob.tsx
···
useNavigate,
useParams,
} from "@solidjs/router";
-
import { Show } from "solid-js";
+
import { createMemo, createResource, onMount, Show } from "solid-js";
import { CodeBlock } from "../../elements/code_block";
+
import { formatBytes } from "../../util/bytes";
import { getLanguage } from "../../util/get_language";
import { figureOutDid } from "../../util/handle";
+
import { Header } from "./components/header";
+
import { PathBar } from "./components/pathbar";
import { useDid } from "./context";
-
import { Header } from "./main";
-
import { getRepoBlob } from "./main.data";
+
import { getRepoBlob, getRepoBlobUrl, getRepoDefaultBranch } from "./main.data";
export async function preloadRepoBlob({ params }: { params: Params }) {
-
const did = await figureOutDid(params.user);
+
const did = await figureOutDid(params.user!);
if (!did) return;
-
getRepoBlob(did, params.repo, params.ref, params.path);
+
getRepoBlob(did, params.repo!, params.ref!, params.path!);
}
export default function RepoBlob() {
-
const params = useParams();
+
const params = useParams() as {
+
user: string;
+
repo: string;
+
ref: string;
+
path: string;
+
};
const did = useDid();
const navigate = useNavigate();
···
})(),
);
+
const blobUrl = createAsync(async () => {
+
const d = did();
+
if (!d) return;
+
return await getRepoBlobUrl(d, params.repo, params.ref, params.path);
+
});
+
+
const codeBlock = createMemo(() => {
+
if (!blob()?.content) return;
+
return (
+
<CodeBlock
+
code={blob()!.content!}
+
language={getLanguage(blob()!.path.split("/").pop()) || "text"}
+
/>
+
);
+
});
+
+
const [defaultBranch] = createResource(did, async (did) => {
+
const res = await getRepoDefaultBranch(did, params.repo);
+
if (!res.ok) return;
+
return res.data.name;
+
});
+
+
const ref = () => params.ref || defaultBranch();
+
+
onMount(() => {
+
if (window.location.hash) {
+
const element = document.getElementById(window.location.hash.slice(1));
+
if (element)
+
element.scrollIntoView({ behavior: "instant", block: "start" });
+
}
+
});
+
return (
<div class="mx-auto max-w-5xl">
<Header user={params.user} repo={params.repo} />
-
<div class="flex flex-col rounded bg-white dark:bg-gray-800">
-
<Show when={blob()} keyed>
-
{(data) => (
-
<CodeBlock
-
code={data.content}
-
language={getLanguage(data.path.split("/").pop()) || "text"}
-
/>
-
)}
-
</Show>
+
<div class="flex flex-col rounded bg-white py-2 dark:bg-gray-800">
+
<div class="mx-5 flex flex-col justify-between gap-1 border-gray-300 border-b py-2 md:flex-row md:items-center dark:border-gray-700">
+
<PathBar
+
user={params.user}
+
repo={params.repo}
+
gitref={ref()!}
+
path={params.path}
+
is_file={true}
+
/>
+
<div class="text-gray-500 text-xs dark:text-gray-400">
+
<Show when={blobUrl() && ref() && blob()}>
+
<span>
+
{"at "}
+
<a
+
href={`/${params.user}/${params.repo}/tree/${ref()!}`}
+
class="text-black hover:text-gray-700 hover:underline dark:text-white hover:dark:text-gray-300"
+
>
+
{ref()!}
+
</a>
+
</span>
+
<span class="select-none px-1 before:content-['\00B7']" />
+
<span>{formatBytes(blob()!.size!)}</span>
+
<span class="select-none px-1 before:content-['\00B7']" />
+
<a
+
href={blobUrl()}
+
class="text-black hover:text-gray-700 hover:underline dark:text-white hover:dark:text-gray-300"
+
>
+
view raw
+
</a>
+
</Show>
+
</div>
+
</div>
+
<div class="flex flex-col p-4">{codeBlock()}</div>
</div>
</div>
);
-61
src/routes/repo/commit/commit.data.ts
···
-
export interface TreeNode {
-
name: string;
-
fullPath: string;
-
type: "file" | "directory";
-
children?: TreeNode[];
-
}
-
-
type BuildNode = {
-
children: { [key: string]: BuildNode };
-
};
-
-
export function buildTree(paths: string[]): TreeNode {
-
// sorry i used claude for this
-
const root: { [key: string]: BuildNode } = {};
-
-
for (const path of paths) {
-
const parts = path.split("/");
-
let current = root;
-
-
for (let i = 0; i < parts.length; i++) {
-
const part = parts[i];
-
current[part] ??= { children: {} };
-
if (i < parts.length - 1) {
-
current = current[part].children;
-
}
-
}
-
}
-
-
const entries = (obj: BuildNode["children"], path: string) =>
-
Object.entries(obj)
-
.map(([k, v]) => convert(path, v, k))
-
.sort((a, b) => {
-
if (a.type !== b.type) return a.type === "directory" ? -1 : 1;
-
-
const aDot = a.name.startsWith(".");
-
const bDot = b.name.startsWith(".");
-
if (aDot !== bDot) return aDot ? -1 : 1;
-
-
return a.name.localeCompare(b.name, undefined, { numeric: true });
-
});
-
-
const convert = (path: string, node: BuildNode, name: string): TreeNode => {
-
const hasChildren = Object.keys(node.children).length > 0;
-
const fullPath = `${path}${name}`;
-
return {
-
name,
-
type: hasChildren ? "directory" : "file",
-
fullPath,
-
children: hasChildren
-
? entries(node.children, `${fullPath}/`)
-
: undefined,
-
};
-
};
-
-
return {
-
name: "",
-
fullPath: "",
-
type: "directory",
-
children: entries(root, ""),
-
};
-
}
-376
src/routes/repo/commit/commit.tsx
···
-
import { useParams } from "@solidjs/router";
-
import {
-
createMemo,
-
createResource,
-
createSignal,
-
For,
-
Match,
-
onMount,
-
Show,
-
Suspense,
-
Switch,
-
} from "solid-js";
-
import type { Commit, DID, DiffTextFragment } from "../../../util/types";
-
import { useDid } from "../context";
-
import { Header } from "../main";
-
import { getRepoCommit } from "../main.data";
-
import { buildTree, type TreeNode } from "./commit.data";
-
-
function RenderTree(props: { tree: TreeNode; skip?: boolean }) {
-
if (props.skip)
-
return (
-
<For each={props.tree.children}>
-
{(node) => <RenderTree tree={node} />}
-
</For>
-
);
-
const [displayChildren, setDisplayChildren] = createSignal(true);
-
return (
-
<Switch>
-
<Match when={props.tree.type === "file"}>
-
<a
-
class="flex cursor-default select-none flex-row items-center gap-1 rounded p-1 text-xs hover:bg-gray-100 hover:dark:bg-gray-700"
-
href={`#file-${props.tree.fullPath}`}
-
>
-
<div class="iconify gravity-ui--file" />
-
<span class="select-text">{props.tree.name}</span>
-
</a>
-
</Match>
-
<Match when={props.tree.type === "directory"}>
-
<div
-
class="flex select-none flex-row items-center gap-1 rounded p-1 text-xs hover:bg-gray-100 hover:dark:bg-gray-700"
-
onclick={() => setDisplayChildren(!displayChildren())}
-
>
-
<div class="iconify gravity-ui--folder-fill" />
-
<span class="select-text">{props.tree.name}</span>
-
</div>
-
<div
-
class={`ml-1 flex flex-col border-gray-200 border-l pl-1 dark:border-gray-700 ${displayChildren() ? "" : "hidden"}`}
-
>
-
<For each={props.tree.children}>
-
{(node) => <RenderTree tree={node} />}
-
</For>
-
</div>
-
</Match>
-
</Switch>
-
);
-
}
-
-
function Fragment(props: {
-
file: string;
-
data: DiffTextFragment;
-
index: number;
-
numberSize: number;
-
}) {
-
let lineNumber = props.data.NewPosition;
-
let iOld = props.data.OldPosition;
-
let iNew = props.data.NewPosition;
-
-
return (
-
<Show when={!props.data.is_binary} fallback={<div>binary data</div>}>
-
<Show when={props.index !== 0}>
-
<div class="h-5 w-full select-none bg-gray-100 text-center font-mono text-gray-700 dark:bg-gray-700 dark:text-gray-300">
-
ยทยทยท
-
</div>
-
</Show>
-
<div class="w-full whitespace-pre font-mono">
-
<For each={props.data.Lines}>
-
{(line) => {
-
const lineNumberOld = line.Op === 2 ? "" : (iOld++).toString();
-
const lineNumberNew = line.Op === 1 ? "" : (iNew++).toString();
-
const fillerOld = "โ€‡".repeat(
-
props.numberSize - lineNumberOld.length,
-
);
-
const fillerNew = "โ€‡".repeat(
-
props.numberSize - lineNumberNew.length,
-
);
-
return (
-
<Line
-
file={props.file}
-
index={props.index}
-
line={line}
-
lineNumber={lineNumber++}
-
lineNumberNew={lineNumberNew}
-
lineNumberOld={lineNumberOld}
-
fillerOld={fillerOld}
-
fillerNew={fillerNew}
-
/>
-
);
-
}}
-
</For>
-
</div>
-
</Show>
-
);
-
}
-
-
function Line(props: {
-
file: string;
-
index: number;
-
line: { Op: number; Line: string };
-
lineNumber: number;
-
lineNumberOld: string;
-
lineNumberNew: string;
-
fillerOld: string;
-
fillerNew: string;
-
}) {
-
const id = `line-${props.file}-${props.index}-${props.lineNumber.toString()}`;
-
return (
-
<div
-
class="flex scroll-mt-10 flex-row text-gray-400 *:flex *:flex-row dark:text-gray-500"
-
id={id}
-
>
-
<div class="sticky left-0 select-none border-gray-200 border-r bg-white px-1 *:flex dark:border-gray-700 dark:bg-gray-800">
-
<span class="float-right mr-1 w-1/2 justify-end">
-
<span>{props.fillerOld}</span>
-
<Show when={props.lineNumberOld}>
-
<a
-
class="hover:text-gray-700 hover:underline hover:dark:text-gray-200"
-
href={`#${id}`}
-
>
-
{props.lineNumberOld}
-
</a>
-
</Show>
-
</span>
-
<span class="float-right mr-1 w-1/2 justify-end">
-
{props.fillerNew}
-
<Show when={props.lineNumberNew}>
-
<a
-
class="hover:text-gray-700 hover:underline hover:dark:text-gray-200"
-
href={`#${id}`}
-
>
-
{props.lineNumberNew}
-
</a>
-
</Show>
-
</span>
-
</div>
-
<Switch>
-
<Match when={props.line.Op === 0}>
-
<div class="w-full text-gray-500 dark:text-gray-500">
-
<div class="select-none">{"โ€‡โ€‡โ€‡"}</div>
-
{props.line.Line}
-
</div>
-
</Match>
-
<Match when={props.line.Op === 2}>
-
<div class="w-full bg-green-100 text-green-700 dark:bg-green-800/30 dark:text-green-400">
-
<div class="select-none">{"โ€‡+โ€‡"}</div>
-
{props.line.Line}
-
</div>
-
</Match>
-
<Match when={props.line.Op === 1}>
-
<div class="w-full bg-red-100 text-red-700 dark:bg-red-800/30 dark:text-red-400">
-
<div class="select-none">{"โ€‡-โ€‡"}</div>
-
{props.line.Line}
-
</div>
-
</Match>
-
</Switch>
-
</div>
-
);
-
}
-
-
function DiffView(props: { commit: Commit }) {
-
return (
-
<For each={props.commit.diff.diff}>
-
{(diff) => {
-
const [show, setShow] = createSignal(true);
-
const [addedLines, removedLines] = diff.text_fragments.reduce(
-
(acc, v) => [acc[0] + v.NewLines, acc[1] + v.LinesDeleted],
-
[0, 0],
-
);
-
-
const lastFrag = diff.text_fragments[diff.text_fragments.length - 1];
-
const numberSize = Math.max(
-
2,
-
(
-
Math.max(lastFrag.NewPosition, lastFrag.OldPosition) +
-
lastFrag.Lines.length
-
).toString().length,
-
);
-
-
return (
-
<div
-
id={`file-${diff.name.new}`}
-
class="not-last:mb-1 flex w-full flex-col rounded border border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-800"
-
>
-
<div
-
class={`sticky top-0 z-10 flex cursor-default select-none flex-row items-center gap-2 bg-white p-2 hover:bg-gray-100 dark:bg-gray-800 hover:dark:bg-gray-700 ${show() ? "rounded-t border-gray-200 border-b dark:border-gray-700" : "rounded"}`}
-
onclick={() => setShow(!show())}
-
>
-
<div
-
class={`iconify ${show() ? "gravity-ui--chevron-down" : "gravity-ui--chevron-right"}`}
-
/>
-
<div class="flex h-6 select-text flex-row items-center overflow-hidden rounded font-mono text-xs *:h-full *:content-center *:px-1">
-
<Show when={addedLines > 0}>
-
<div class="bg-green-100 text-green-700 dark:bg-green-800/30 dark:text-green-400">{`+${addedLines}`}</div>
-
</Show>
-
<Show when={removedLines > 0}>
-
<div class="bg-red-100 text-red-700 dark:bg-red-700/30 dark:text-red-400">{`-${removedLines}`}</div>
-
</Show>
-
</div>
-
<Show
-
when={diff.name.old !== "" && diff.name.new !== diff.name.old}
-
>
-
<div class="select-text">{diff.name.old}</div>
-
<div class="iconify gravity-ui--arrow-right" />
-
</Show>
-
<div class="select-text">{diff.name.new}</div>
-
</div>
-
<div
-
class={`select-text overflow-x-auto rounded-b bg-white dark:bg-gray-800 ${show() ? "" : "hidden"}`}
-
>
-
<div class="min-w-max">
-
<For each={diff.text_fragments}>
-
{(frag, i) => (
-
<Fragment
-
file={diff.name.new}
-
data={frag}
-
index={i()}
-
numberSize={numberSize}
-
/>
-
)}
-
</For>
-
</div>
-
</div>
-
</div>
-
);
-
}}
-
</For>
-
);
-
}
-
-
function CommitHeader(props: {
-
user: string;
-
repo: string;
-
message: { title: string; content: string };
-
commit: Commit;
-
}) {
-
return (
-
<div>
-
<Header user={props.user} repo={props.repo} />
-
<div class="mx-1 flex flex-col gap-2 rounded bg-white p-4 dark:bg-gray-800">
-
<div>{props.message.title}</div>
-
<Show when={props.message.content}>
-
<div class="text-xs">{props.message.content}</div>
-
</Show>
-
<div class="text-gray-500 text-xs dark:text-gray-300">
-
<span>{`${new Date(props.commit.diff.commit.author.When).toLocaleDateString(undefined, { dateStyle: "long" })} at ${new Date(props.commit.diff.commit.author.When).toLocaleTimeString()}`}</span>
-
<span class="select-none px-1 before:content-['\00B7']" />
-
<span>{`${props.commit.diff.commit.author.Name} <${props.commit.diff.commit.author.Email}>`}</span>
-
<span class="select-none px-1 before:content-['\00B7']" />
-
<a
-
class="hover:text-gray-600 hover:underline hover:dark:text-gray-200"
-
href={`/${props.user}/${props.repo}/commit/${props.commit.ref}`}
-
>
-
{props.commit.ref.slice(0, 8)}
-
</a>
-
<Show when={props.commit.diff.commit.parent}>
-
<div class="iconify gravity-ui--arrow-left mx-1 text-[0.6rem]" />
-
<a
-
class="hover:text-gray-600 hover:underline hover:dark:text-gray-200"
-
href={`/${props.user}/${props.repo}/commit/${props.commit.diff.commit.parent}`}
-
>
-
{props.commit.diff.commit.parent.slice(0, 8)}
-
</a>
-
</Show>
-
</div>
-
</div>
-
</div>
-
);
-
}
-
-
export default function RepoCommit() {
-
const params = useParams();
-
const did = useDid();
-
-
const [commit] = createResource(
-
() => {
-
const d = did();
-
if (!d) return;
-
return [d, params.repo, params.ref];
-
},
-
async ([did, repo, ref]) => {
-
const res = await getRepoCommit(did as DID, repo, ref);
-
if (!res.ok) return;
-
return res.data as Commit;
-
},
-
);
-
-
const [sidebar] = createResource(commit, async (commit) => {
-
if (!commit.diff.diff)
-
return { name: "", fullPath: "", type: "directory" } as TreeNode;
-
return buildTree(commit.diff.diff.map((v) => v.name.new));
-
});
-
-
const allData = createMemo(() => {
-
const s = sidebar();
-
const c = commit();
-
if (!(s && c)) return;
-
-
return [s, c] as const;
-
});
-
-
const headerData = createMemo(() => {
-
const c = commit();
-
if (!c) return;
-
-
const titleEnd = c.diff.commit.message.indexOf("\n");
-
const message = {
-
title: c.diff.commit.message.slice(0, titleEnd),
-
content: c.diff.commit.message.slice(titleEnd + 1),
-
};
-
-
return [c, message] as const;
-
});
-
-
onMount(() => {
-
if (window.location.hash) {
-
const element = document.getElementById(window.location.hash.slice(1));
-
if (element)
-
element.scrollIntoView({ behavior: "instant", block: "start" });
-
}
-
});
-
-
return (
-
<div class="mx-auto max-w-10xl">
-
<Suspense>
-
<Show when={headerData()} keyed>
-
{([commit, message]) => (
-
<CommitHeader
-
user={params.user}
-
repo={params.repo}
-
message={message}
-
commit={commit}
-
/>
-
)}
-
</Show>
-
<Show when={allData()} keyed>
-
{([sidebar, commit]) => (
-
<>
-
<div class="flex flex-row gap-1">
-
<div class="sticky top-0 flex max-h-screen min-w-50 overflow-auto p-1 pr-0">
-
<Show when={sidebar.children}>
-
<div class="flex min-h-max w-full grow cursor-default flex-col rounded border border-gray-200 bg-white p-1 dark:border-gray-700 dark:bg-gray-800">
-
<div class="flex flex-row items-center justify-between gap-1 p-1">
-
<div class="font-bold">CHANGED FILES</div>
-
<div class="flex h-6 select-text flex-row items-center overflow-hidden rounded font-mono text-xs *:h-full *:content-center *:px-1">
-
<Show when={commit.diff.stat.insertions > 0}>
-
<div class="bg-green-100 text-green-700 dark:bg-green-800/30 dark:text-green-400">{`+${commit.diff.stat.insertions}`}</div>
-
</Show>
-
<Show when={commit.diff.stat.deletions > 0}>
-
<div class="bg-red-100 text-red-700 dark:bg-red-700/30 dark:text-red-400">{`-${commit.diff.stat.deletions}`}</div>
-
</Show>
-
</div>
-
</div>
-
<RenderTree tree={sidebar} skip={true} />
-
</div>
-
</Show>
-
</div>
-
<div class="min-w-0 flex-1 flex-col gap-1 p-1 pl-0">
-
<DiffView commit={commit} />
-
</div>
-
</div>
-
</>
-
)}
-
</Show>
-
</Suspense>
-
</div>
-
);
-
}
+5
src/routes/repo/commits.tsx
···
+
import { useParams } from "@solidjs/router";
+
+
export function RepoCommits() {
+
const params = useParams();
+
}
+121
src/routes/repo/components/header.tsx
···
+
import { type Accessor, createMemo, createResource, Show } from "solid-js";
+
import { getUserRepoByRkey } from "../../../util/get_repo";
+
import { figureOutHandle } from "../../../util/handle";
+
import type { DID } from "../../../util/types";
+
import { useRepoInfo } from "../context";
+
+
function HeaderItem(props: {
+
path: string;
+
title: string;
+
icon: string;
+
windowPath: Accessor<string>;
+
}) {
+
return (
+
<a
+
class={`flex h-full w-min flex-row content-center items-center gap-2 rounded-t px-4 py-1 ${props.windowPath() === props.title ? "bg-white dark:bg-gray-800" : "hover:dark:bg-gray-700/25"}`}
+
href={props.path}
+
>
+
<div class={`iconify ${props.icon}`} />
+
{props.title}
+
</a>
+
);
+
}
+
+
export function Header(props: { user: string; repo: string }) {
+
const repoInfo = useRepoInfo();
+
const path = createMemo(() => {
+
const path = window.location.pathname.split("/")[3];
+
return ["issues", "pulls", "pipelines"].includes(path) ? path : "overview";
+
});
+
+
const [forkedInfo] = createResource(
+
() => repoInfo()?.repo,
+
(repo) =>
+
(async () => {
+
if (!repo.source) return;
+
const [, , did, , rkey] = repo.source.split("/");
+
if (rkey === repo.rkey) return;
+
return {
+
did: did as DID,
+
repo: await getUserRepoByRkey(did as DID, rkey),
+
};
+
})(),
+
);
+
+
const [forkedHandle] = createResource(forkedInfo, (forkedInfo) =>
+
(async () => await figureOutHandle(forkedInfo.did))(),
+
);
+
+
return (
+
<Show when={repoInfo()} keyed>
+
{(repoInfo) => (
+
<div class="flex flex-col">
+
<div class="m-5 mt-0 flex flex-row items-center justify-between gap-0.5">
+
<div class="flex flex-col gap-1 text-xs">
+
<Show when={forkedInfo()?.repo && forkedHandle()} keyed>
+
<div class="flex flex-row items-center gap-1">
+
<div class="iconify gravity-ui--code-fork" />
+
<span>
+
forked from{" "}
+
<a
+
href={`/${forkedHandle()}/${forkedInfo()!.repo!.name}`}
+
class="underline hover:text-gray-700 dark:hover:text-gray-200"
+
>{`@${forkedHandle()}/${forkedInfo()!.repo!.name}`}</a>
+
</span>
+
</div>
+
</Show>
+
<div class="flex flex-row items-center gap-1 text-base">
+
<a
+
class="hover:text-gray-700 hover:underline dark:hover:text-gray-200"
+
href={`/${props.user}`}
+
>
+
@{props.user}
+
</a>
+
<span class="select-none text-xl">/</span>
+
<a
+
class="font-bold hover:text-gray-700 hover:underline dark:hover:text-gray-200"
+
href={`/${props.user}/${props.repo}`}
+
>
+
{props.repo}
+
</a>
+
</div>
+
<Show when={repoInfo.repo} keyed>
+
{(repo) => <div class="text-xs">{repo.description}</div>}
+
</Show>
+
</div>
+
<div class="flex flex-row gap-2">
+
<button
+
type="button"
+
class="btn flex flex-row items-center gap-1"
+
>
+
<div class="iconify gravity-ui--star" />
+
{repoInfo.stars.toString() || "0"}
+
</button>
+
<button
+
type="button"
+
class="btn flex flex-row items-center gap-1"
+
>
+
<div class="iconify gravity-ui--code-fork" />
+
{repoInfo.forks.toString() || "0"}
+
</button>
+
</div>
+
</div>
+
<div class="mx-4 flex flex-row gap-1">
+
<HeaderItem
+
title="overview"
+
path={`/${props.user}/${props.repo}`}
+
icon="gravity-ui--square-list-ul"
+
windowPath={path}
+
/>
+
{/*<HeaderItem
+
title="issues"
+
path={`/${props.user}/${props.repo}/issues`}
+
icon="gravity-ui--circle-minus"
+
windowPath={path}
+
/>*/}
+
</div>
+
</div>
+
)}
+
</Show>
+
);
+
}
+54
src/routes/repo/components/pathbar.tsx
···
+
import { createMemo, For, Show } from "solid-js";
+
+
export function PathBar(props: {
+
user: string;
+
repo: string;
+
gitref: string;
+
path: string;
+
is_file: boolean;
+
}) {
+
const paths = createMemo(() => {
+
const names = props.path.split("/");
+
const paths = new Array(names.length) as string[];
+
let i = 0;
+
for (const name of names) {
+
paths[i] = `${paths.at(i - 1) || ""}/${name}`;
+
i += 1;
+
}
+
return names.map((name, i) => ({ name, path: paths.at(i) }));
+
});
+
+
return (
+
<div class="flex flex-row gap-1 overflow-x-auto">
+
<a
+
href={`/${props.user}/${props.repo}/tree/${props.gitref}`}
+
class="text-gray-600 hover:text-gray-700 hover:underline dark:text-gray-400 hover:dark:text-gray-300"
+
>
+
{props.repo}
+
</a>
+
<span class="text-gray-400 dark:text-gray-600">/</span>
+
<For each={paths()}>
+
{(v, i) => (
+
<>
+
<Show
+
when={props.is_file && i() === paths().length - 1}
+
fallback={
+
<a
+
href={`/${props.user}/${props.repo}/tree/${props.gitref}${v.path}`}
+
class="text-gray-600 hover:text-gray-700 hover:underline dark:text-gray-400 hover:dark:text-gray-300"
+
>
+
{v.name}
+
</a>
+
}
+
>
+
<span>{v.name}</span>
+
</Show>
+
<Show when={!(props.is_file && i() === paths().length - 1)}>
+
<span class="text-gray-400 dark:text-gray-600">/</span>
+
</Show>
+
</>
+
)}
+
</For>
+
</div>
+
);
+
}
+139
src/routes/repo/diff/commit.tsx
···
+
import { type Params, useParams } from "@solidjs/router";
+
import { createMemo, createResource, onMount, Show } from "solid-js";
+
import { figureOutDid } from "../../../util/handle";
+
import { toRelativeTime } from "../../../util/time";
+
import type { Commit, DID } from "../../../util/types";
+
import { Header } from "../components/header";
+
import { useDid } from "../context";
+
import { getRepoCommit } from "../main.data";
+
import { buildTree, type TreeNode } from "./data";
+
import { DiffView, Sidebar } from "./generic";
+
+
export async function preloadRepoCommit({ params }: { params: Params }) {
+
const did = await figureOutDid(params.user!);
+
if (!did) return;
+
getRepoCommit(did, params.repo!, params.ref!);
+
}
+
+
export default function RepoCommit() {
+
const params = useParams() as { user: string; repo: string; ref: string };
+
const did = useDid();
+
+
const [commit] = createResource(
+
() => {
+
const d = did();
+
if (!d) return;
+
return [d, params.repo, params.ref] as const;
+
},
+
async ([did, repo, ref]) => {
+
const res = await getRepoCommit(did as DID, repo, ref);
+
if (!res.ok) return;
+
return res.data as Commit;
+
},
+
);
+
+
const commitDiffViewInput = createMemo(() => {
+
if (!commit()?.diff) return;
+
return commit()!.diff.diff.map((diff) => ({
+
oldName: diff.name.old,
+
newName: diff.name.new,
+
textFragments: diff.text_fragments,
+
}));
+
});
+
+
const sidebar = createMemo(() => {
+
if (!commit()?.diff.diff)
+
return { name: "", fullPath: "", type: "directory" } as TreeNode;
+
return buildTree(commit()!.diff.diff.map((v) => v.name.new));
+
});
+
+
const message = createMemo(() => {
+
const c = commit();
+
if (!c) return;
+
+
const titleEnd = c.diff.commit.message.indexOf("\n");
+
return {
+
title: c.diff.commit.message.slice(0, titleEnd),
+
content: c.diff.commit.message.slice(titleEnd + 1),
+
};
+
});
+
+
onMount(() => {
+
if (window.location.hash) {
+
const element = document.getElementById(window.location.hash.slice(1));
+
if (element)
+
element.scrollIntoView({ behavior: "instant", block: "start" });
+
}
+
});
+
+
return (
+
<div class="mx-auto max-w-10xl">
+
<Show when={commit() && message()}>
+
<CommitHeader
+
user={params.user}
+
repo={params.repo}
+
message={message()!}
+
commit={commit()!}
+
/>
+
</Show>
+
<Show when={sidebar()?.children && commit() && commitDiffViewInput()}>
+
<div class="flex flex-col gap-1 md:flex-row">
+
<Sidebar
+
sidebar={sidebar()}
+
insertions={commit()!.diff.stat.insertions}
+
deletions={commit()!.diff.stat.deletions}
+
/>
+
<div class="min-w-0 flex-1 flex-col gap-1 p-1 max-md:pt-0 md:pl-0">
+
<DiffView diff={commitDiffViewInput()!} />
+
</div>
+
</div>
+
</Show>
+
</div>
+
);
+
}
+
+
function CommitHeader(props: {
+
user: string;
+
repo: string;
+
message: { title: string; content: string };
+
commit: Commit;
+
}) {
+
const date = () => new Date(props.commit.diff.commit.author.When);
+
return (
+
<div>
+
<Header user={props.user} repo={props.repo} />
+
<div class="mx-1 flex flex-col gap-2 rounded bg-white p-4 dark:bg-gray-800">
+
<div>{props.message.title}</div>
+
<Show when={props.message.content}>
+
<div class="text-xs">{props.message.content}</div>
+
</Show>
+
<div class="text-gray-500 text-xs dark:text-gray-300">
+
<span
+
title={date().toLocaleString(undefined, {
+
dateStyle: "full",
+
timeStyle: "short",
+
})}
+
>{`${toRelativeTime(date())}`}</span>
+
<span class="select-none px-1 before:content-['\00B7']" />
+
<span>{`${props.commit.diff.commit.author.Name} <${props.commit.diff.commit.author.Email}>`}</span>
+
<span class="select-none px-1 before:content-['\00B7']" />
+
<a
+
class="hover:text-gray-600 hover:underline hover:dark:text-gray-200"
+
href={`/${props.user}/${props.repo}/commit/${props.commit.ref}`}
+
>
+
{props.commit.ref.slice(0, 8)}
+
</a>
+
<Show when={props.commit.diff.commit.parent}>
+
<div class="iconify gravity-ui--arrow-left mx-1 text-[0.6rem]" />
+
<a
+
class="hover:text-gray-600 hover:underline hover:dark:text-gray-200"
+
href={`/${props.user}/${props.repo}/commit/${props.commit.diff.commit.parent}`}
+
>
+
{props.commit.diff.commit.parent.slice(0, 8)}
+
</a>
+
</Show>
+
</div>
+
</div>
+
</div>
+
);
+
}
+109
src/routes/repo/diff/compare.tsx
···
+
import { type Params, useParams } from "@solidjs/router";
+
import { createMemo, createResource, onMount, Show } from "solid-js";
+
import { figureOutDid } from "../../../util/handle";
+
import type { Compare, DID } from "../../../util/types";
+
import { Header } from "../components/header";
+
import { useDid } from "../context";
+
import { getRepoCommit, getRepoCompare } from "../main.data";
+
import { buildTree, type TreeNode } from "./data";
+
import { DiffView, Sidebar } from "./generic";
+
+
export async function preloadRepoCompare({ params }: { params: Params }) {
+
const did = await figureOutDid(params.user!);
+
if (!did) return;
+
getRepoCommit(did, params.repo!, params.ref!);
+
}
+
+
export default function RepoCompare() {
+
const params = useParams() as {
+
user: string;
+
repo: string;
+
base: string;
+
compare: string;
+
};
+
const did = useDid();
+
+
const [compare] = createResource(
+
() => {
+
const d = did();
+
if (!d) return;
+
return [d, params.repo, params.base, params.compare] as const;
+
},
+
async ([did, repo, base, compare]) => {
+
const res = await getRepoCompare(did as DID, repo, base, compare);
+
if (!res.ok) return;
+
return res.data as Compare;
+
},
+
);
+
+
const compareDiffViewInput = createMemo(() => {
+
if (!compare()?.combined_patch) return;
+
return compare()!.combined_patch!.map((diff) => ({
+
oldName: diff.OldName,
+
newName: diff.NewName,
+
textFragments: diff.TextFragments || [],
+
}));
+
});
+
+
const sidebar = createMemo(() => {
+
if (!compare()?.combined_patch)
+
return { name: "", fullPath: "", type: "directory" } as TreeNode;
+
const set = new Set(
+
compare()!.combined_patch!.flatMap((file) => [
+
file.NewName,
+
file.OldName,
+
]),
+
);
+
set.delete("");
+
return buildTree(set);
+
});
+
+
const compareNumbers = createMemo(() => {
+
if (!compare()?.combined_patch) return { insertions: 0, deletions: 0 };
+
let [insertions, deletions] = [0, 0];
+
compare()!.combined_patch!.forEach((file) => {
+
if (!file.TextFragments) return;
+
file.TextFragments.forEach((fragment) => {
+
insertions += fragment.LinesAdded;
+
deletions += fragment.LinesDeleted;
+
});
+
});
+
return { insertions, deletions };
+
});
+
+
onMount(() => {
+
if (window.location.hash) {
+
const element = document.getElementById(window.location.hash.slice(1));
+
if (element)
+
element.scrollIntoView({ behavior: "instant", block: "start" });
+
}
+
});
+
+
return (
+
<div class="mx-auto max-w-10xl">
+
<Show when={compare()}>
+
<CommitHeader user={params.user} repo={params.repo} />
+
</Show>
+
<Show when={sidebar()?.children && compare() && compareDiffViewInput()}>
+
<div class="flex flex-col gap-1 md:flex-row">
+
<Sidebar
+
sidebar={sidebar()}
+
insertions={compareNumbers().insertions}
+
deletions={compareNumbers().deletions}
+
/>
+
<div class="min-w-0 flex-1 flex-col gap-1 p-1 max-md:pt-0 md:pl-0">
+
<DiffView diff={compareDiffViewInput()!} />
+
</div>
+
</div>
+
</Show>
+
</div>
+
);
+
}
+
+
function CommitHeader(props: { user: string; repo: string }) {
+
return (
+
<div>
+
<Header user={props.user} repo={props.repo} />
+
</div>
+
);
+
}
+61
src/routes/repo/diff/data.ts
···
+
export interface TreeNode {
+
name: string;
+
fullPath: string;
+
type: "file" | "directory";
+
children?: TreeNode[];
+
}
+
+
type BuildNode = {
+
children: { [key: string]: BuildNode };
+
};
+
+
export function buildTree(paths: string[] | Set<string>): TreeNode {
+
// sorry i used claude for this
+
const root: { [key: string]: BuildNode } = {};
+
+
for (const path of paths) {
+
const parts = path.split("/");
+
let current = root;
+
+
for (let i = 0; i < parts.length; i++) {
+
const part = parts[i];
+
current[part] ??= { children: {} };
+
if (i < parts.length - 1) {
+
current = current[part].children;
+
}
+
}
+
}
+
+
const entries = (obj: BuildNode["children"], path: string) =>
+
Object.entries(obj)
+
.map(([k, v]) => convert(path, v, k))
+
.sort((a, b) => {
+
if (a.type !== b.type) return a.type === "directory" ? -1 : 1;
+
+
const aDot = a.name.startsWith(".");
+
const bDot = b.name.startsWith(".");
+
if (aDot !== bDot) return aDot ? -1 : 1;
+
+
return a.name.localeCompare(b.name, undefined, { numeric: true });
+
});
+
+
const convert = (path: string, node: BuildNode, name: string): TreeNode => {
+
const hasChildren = Object.keys(node.children).length > 0;
+
const fullPath = `${path}${name}`;
+
return {
+
name,
+
type: hasChildren ? "directory" : "file",
+
fullPath,
+
children: hasChildren
+
? entries(node.children, `${fullPath}/`)
+
: undefined,
+
};
+
};
+
+
return {
+
name: "",
+
fullPath: "",
+
type: "directory",
+
children: entries(root, ""),
+
};
+
}
+298
src/routes/repo/diff/generic.tsx
···
+
import { createSignal, For, Match, Show, Switch } from "solid-js";
+
import type { DiffTextFragment } from "../../../util/types";
+
import type { TreeNode } from "./data";
+
+
export function RenderTree(props: { tree: TreeNode; skip?: boolean }) {
+
if (props.skip)
+
return (
+
<For each={props.tree.children}>
+
{(node) => <RenderTree tree={node} />}
+
</For>
+
);
+
const [displayChildren, setDisplayChildren] = createSignal(true);
+
return (
+
<Switch>
+
<Match when={props.tree.type === "file"}>
+
<a
+
class="flex min-w-fit cursor-default select-none flex-row items-center gap-1 rounded p-1 text-xs hover:bg-gray-100 hover:dark:bg-gray-700"
+
href={`#file-${encodeURI(props.tree.fullPath)}`}
+
onClick={() => {
+
const hash = `#file-${encodeURI(props.tree.fullPath)}`;
+
if (window.location.hash === hash) {
+
document
+
.getElementById(`file-${props.tree.fullPath}`)
+
?.scrollIntoView({ behavior: "instant", block: "start" });
+
}
+
}}
+
>
+
<div class="iconify gravity-ui--file" />
+
<span class="select-text">{props.tree.name}</span>
+
</a>
+
</Match>
+
<Match when={props.tree.type === "directory"}>
+
<button
+
type="button"
+
class="flex min-w-fit select-none flex-row items-center gap-1 rounded p-1 text-xs hover:bg-gray-100 hover:dark:bg-gray-700"
+
onClick={() => setDisplayChildren(!displayChildren())}
+
>
+
<div class="iconify gravity-ui--folder-fill" />
+
<span class="select-text">{props.tree.name}</span>
+
</button>
+
<div
+
class={`ml-1 flex flex-col border-gray-200 border-l pl-1 dark:border-gray-700 ${displayChildren() ? "" : "hidden"}`}
+
>
+
<For each={props.tree.children}>
+
{(node) => <RenderTree tree={node} />}
+
</For>
+
</div>
+
</Match>
+
</Switch>
+
);
+
}
+
+
function Line(props: {
+
file: string;
+
index: number;
+
line: { Op: number; Line: string };
+
lineNumber: number;
+
lineNumberOld: string;
+
lineNumberNew: string;
+
filler: string;
+
}) {
+
const id = `line-${encodeURI(props.file)}-${props.index}-${props.lineNumber.toString()}`;
+
return (
+
<div
+
class="flex scroll-mt-10 flex-row text-gray-400 *:flex *:flex-row dark:text-gray-500"
+
id={id}
+
>
+
<div class="sticky left-0 select-none border-gray-200 border-r bg-white *:flex dark:border-gray-700 dark:bg-gray-800">
+
<Show
+
when={props.lineNumberOld}
+
fallback={
+
<span class="float-right w-1/2 justify-end pr-1 pl-1.5">
+
{props.filler}
+
</span>
+
}
+
>
+
<a
+
href={`#${id}`}
+
class="float-right w-1/2 justify-end pr-1 pl-1.5 hover:text-gray-700 hover:dark:text-gray-200"
+
>
+
{props.lineNumberOld}
+
</a>
+
</Show>
+
<Show
+
when={props.lineNumberNew}
+
fallback={
+
<span class="float-right w-1/2 justify-end pr-1.5 pl-1">
+
{props.filler}
+
</span>
+
}
+
>
+
<a
+
href={`#${id}`}
+
class="float-right w-1/2 justify-end pr-1.5 pl-1 hover:text-gray-700 hover:dark:text-gray-200"
+
>
+
{props.lineNumberNew}
+
</a>
+
</Show>
+
</div>
+
<Switch>
+
<Match when={props.line.Op === 0}>
+
<div class="w-full text-gray-500 dark:text-gray-500">
+
<div class="select-none">{"โ€‡โ€‡โ€‡"}</div>
+
{props.line.Line}
+
</div>
+
</Match>
+
<Match when={props.line.Op === 2}>
+
<div class="w-full bg-green-100 text-green-700 dark:bg-green-800/30 dark:text-green-400">
+
<div class="select-none">{"โ€‡+โ€‡"}</div>
+
{props.line.Line}
+
</div>
+
</Match>
+
<Match when={props.line.Op === 1}>
+
<div class="w-full bg-red-100 text-red-700 dark:bg-red-800/30 dark:text-red-400">
+
<div class="select-none">{"โ€‡-โ€‡"}</div>
+
{props.line.Line}
+
</div>
+
</Match>
+
</Switch>
+
</div>
+
);
+
}
+
+
function Fragment(props: {
+
file: string;
+
data: DiffTextFragment;
+
index: number;
+
numberSize: number;
+
}) {
+
let lineNumber = props.data.NewPosition;
+
let iOld = props.data.OldPosition;
+
let iNew = props.data.NewPosition;
+
+
return (
+
<>
+
<Show when={props.index !== 0}>
+
<div class="h-5 w-full select-none bg-gray-100 text-center font-mono text-gray-700 dark:bg-gray-700 dark:text-gray-300">
+
ยทยทยท
+
</div>
+
</Show>
+
<div class="w-full whitespace-pre font-mono">
+
<For each={props.data.Lines}>
+
{(line) => {
+
const lineNumberOld =
+
line.Op === 2
+
? ""
+
: (iOld++).toString().padStart(props.numberSize, "โ€‡");
+
const lineNumberNew =
+
line.Op === 1
+
? ""
+
: (iNew++).toString().padStart(props.numberSize, "โ€‡");
+
const filler = "โ€‡".repeat(props.numberSize);
+
return (
+
<Line
+
file={props.file}
+
index={props.index}
+
line={line}
+
lineNumber={lineNumber++}
+
lineNumberNew={lineNumberNew}
+
lineNumberOld={lineNumberOld}
+
filler={filler}
+
/>
+
);
+
}}
+
</For>
+
</div>
+
</>
+
);
+
}
+
+
export function DiffView(props: {
+
diff: {
+
oldName: string;
+
newName: string;
+
textFragments: DiffTextFragment[];
+
}[];
+
}) {
+
return (
+
<For each={props.diff}>
+
{(diff) => {
+
const [show, setShow] = createSignal(true);
+
+
const [addedLines, removedLines] = diff.textFragments
+
? diff.textFragments.reduce(
+
(acc, v) => [acc[0] + v.NewLines, acc[1] + v.LinesDeleted],
+
[0, 0],
+
)
+
: [0, 0];
+
+
const header = (
+
<button
+
type="button"
+
class={`sticky top-0 z-10 flex cursor-default select-none flex-row items-center gap-2 bg-white p-2 hover:bg-gray-100 dark:bg-gray-800 hover:dark:bg-gray-700 ${show() ? "rounded-t border-gray-200 border-b dark:border-gray-700" : "rounded"}`}
+
onClick={() => setShow(!show())}
+
>
+
<div
+
class={`iconify ${show() ? "gravity-ui--chevron-down" : "gravity-ui--chevron-right"}`}
+
/>
+
<div class="flex h-6 select-text flex-row items-center overflow-hidden rounded font-mono text-xs *:h-full *:content-center *:px-1">
+
<Show when={addedLines > 0}>
+
<div class="bg-green-100 text-green-700 dark:bg-green-800/30 dark:text-green-400">{`+${addedLines}`}</div>
+
</Show>
+
<Show when={removedLines > 0}>
+
<div class="bg-red-100 text-red-700 dark:bg-red-700/30 dark:text-red-400">{`-${removedLines}`}</div>
+
</Show>
+
</div>
+
<Show when={diff.oldName !== "" && diff.newName !== diff.oldName}>
+
<div class="select-text">{diff.oldName}</div>
+
<div class="iconify gravity-ui--arrow-right" />
+
</Show>
+
<Show
+
when={diff.newName !== ""}
+
fallback={<div class="iconify gravity-ui--trash-bin" />}
+
>
+
<div class="select-text">{diff.newName}</div>
+
</Show>
+
</button>
+
);
+
+
if (!diff.textFragments)
+
return (
+
<div
+
id={`file-${encodeURI(diff.newName)}`}
+
class="not-last:mb-1 flex w-full flex-col rounded border border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-800"
+
>
+
{header}
+
<div
+
class={`flex select-text justify-center rounded-b bg-white py-2 text-gray-500 dark:bg-gray-800 dark:text-gray-300 ${show() ? "" : "hidden"}`}
+
>
+
This is a binary file and will not be displayed.
+
</div>
+
</div>
+
);
+
+
const lastFrag = diff.textFragments[diff.textFragments.length - 1];
+
const numberSize = Math.max(
+
2,
+
(
+
Math.max(lastFrag.NewPosition, lastFrag.OldPosition) +
+
lastFrag.Lines.length
+
).toString().length,
+
);
+
+
return (
+
<div
+
id={`file-${diff.newName}`}
+
class="not-last:mb-1 flex w-full flex-col rounded border border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-800"
+
>
+
{header}
+
<div
+
class={`select-text overflow-x-auto rounded-b bg-white dark:bg-gray-800 ${show() ? "" : "hidden"}`}
+
>
+
<div class="min-w-max">
+
<For each={diff.textFragments}>
+
{(frag, i) => (
+
<Fragment
+
file={diff.newName}
+
data={frag}
+
index={i()}
+
numberSize={numberSize}
+
/>
+
)}
+
</For>
+
</div>
+
</div>
+
</div>
+
);
+
}}
+
</For>
+
);
+
}
+
+
export function Sidebar(props: {
+
insertions: number;
+
deletions: number;
+
sidebar: TreeNode;
+
}) {
+
return (
+
<div class="flex overflow-y-auto p-1 max-md:pb-0 md:sticky md:top-0 md:max-h-screen md:w-50 md:pr-0">
+
<div class="flex min-h-max w-full grow cursor-default flex-col rounded border border-gray-200 bg-white p-1 dark:border-gray-700 dark:bg-gray-800">
+
<div class="flex flex-row items-center justify-between p-1">
+
<div class="font-bold">CHANGED FILES</div>
+
<div class="flex h-6 select-text flex-row items-center overflow-clip rounded font-mono text-xs *:h-full *:content-center *:px-1">
+
<Show when={props.insertions > 0}>
+
<div class="bg-green-100 text-green-700 dark:bg-green-800/30 dark:text-green-400">{`+${props.insertions}`}</div>
+
</Show>
+
<Show when={props.deletions > 0}>
+
<div class="bg-red-100 text-red-700 dark:bg-red-700/30 dark:text-red-400">{`-${props.deletions}`}</div>
+
</Show>
+
</div>
+
</div>
+
<div class="flex max-w-full flex-col overflow-x-auto text-nowrap">
+
<RenderTree tree={props.sidebar} skip={true} />
+
</div>
+
</div>
+
</div>
+
);
+
}
+35 -4
src/routes/repo/main.data.ts
···
return rpc;
}
+
async function getConstellationRpc() {
+
const handler = simpleFetchHandler({ service: constellationUrl });
+
const rpc = new Client({ handler });
+
+
return rpc;
+
}
+
export const getRepoDefaultBranch = query(async (user: DID, repo: string) => {
const rpc = await getKnotRpc(user, repo);
···
return await rpc.get("sh.tangled.repo.tree", {
params: {
repo: `${user}/${repo}`,
-
ref,
-
path,
+
ref: ref,
+
path: path ?? "",
},
});
},
···
});
},
"RepoBlob",
+
);
+
+
export const getRepoBlobUrl = query(
+
async (user: DID, repo: string, ref: string, path: string) => {
+
const knot = await getRepoKnot(user, repo);
+
+
return `${knot}/xrpc/sh.tangled.repo.blob?repo=${user}/${repo}&ref=${ref}&path=${path}&raw=true`;
+
},
+
"RepoBlobUrl",
);
export const getRepoLog = query(
-
async (user: DID, repo: string, ref: string, path: string) => {
+
async (user: DID, repo: string, ref: string) => {
const rpc = await getKnotRpc(user, repo);
return await rpc.get("sh.tangled.repo.log", {
···
params: {
repo: `${user}/${repo}`,
ref,
-
path,
},
});
},
···
params: {
repo: `${user}/${repo}`,
ref,
+
},
+
});
+
},
+
"RepoCommit",
+
);
+
+
export const getRepoCompare = query(
+
async (user: DID, repo: string, rev1: string, rev2: string) => {
+
const rpc = await getKnotRpc(user, repo);
+
+
return await rpc.get("sh.tangled.repo.compare", {
+
as: "json",
+
params: {
+
repo: `${user}/${repo}`,
+
rev1,
+
rev2,
},
});
},
-85
src/routes/repo/main.tsx
···
-
import { type Accessor, createMemo, Show } from "solid-js";
-
import { useRepoInfo } from "./context";
-
-
function HeaderItem(props: {
-
path: string;
-
title: string;
-
icon: string;
-
windowPath: Accessor<string>;
-
}) {
-
return (
-
<a
-
class={`flex h-full w-min flex-row content-center items-center gap-2 rounded-t px-4 py-1 ${props.windowPath() === props.title ? "bg-white dark:bg-gray-800" : "hover:dark:bg-gray-700/25"}`}
-
href={props.path}
-
>
-
<div class={`iconify ${props.icon}`} />
-
{props.title}
-
</a>
-
);
-
}
-
-
export function Header(props: { user: string; repo: string }) {
-
const repoInfo = useRepoInfo();
-
const path = createMemo(() => {
-
const path = window.location.pathname.split("/")[3];
-
return ["issues", "pulls", "pipelines"].includes(path) ? path : "overview";
-
});
-
-
return (
-
<Show when={repoInfo()} keyed>
-
{(repoInfo) => (
-
<>
-
<div class="m-5 mt-0 flex flex-row items-center justify-between gap-0.5">
-
<div class="flex flex-col gap-1">
-
<div class="flex flex-row items-center gap-1 text-base">
-
<a class="hover:underline" href={`/${props.user}`}>
-
@{props.user}
-
</a>
-
<span class="select-none text-xl">/</span>
-
<a
-
class="font-bold hover:underline"
-
href={`/${props.user}/${props.repo}`}
-
>
-
{props.repo}
-
</a>
-
</div>
-
<Show when={repoInfo.repo} keyed>
-
{(repo) => <div class="text-xs">{repo.description}</div>}
-
</Show>
-
</div>
-
<div class="flex flex-row gap-2">
-
<button
-
type="button"
-
class="btn flex flex-row items-center gap-1"
-
>
-
<div class="iconify gravity-ui--star" />
-
{repoInfo.stars.toString() || "0"}
-
</button>
-
<button
-
type="button"
-
class="btn flex flex-row items-center gap-1"
-
>
-
<div class="iconify gravity-ui--code-fork" />
-
{repoInfo.forks.toString() || "0"}
-
</button>
-
</div>
-
</div>
-
<div class="mx-4 flex flex-row gap-1">
-
<HeaderItem
-
title="overview"
-
path={`/${props.user}/${props.repo}`}
-
icon="gravity-ui--square-list-ul"
-
windowPath={path}
-
/>
-
{/*<HeaderItem
-
title="issues"
-
path={`/${props.user}/${props.repo}/issues`}
-
icon="gravity-ui--circle-minus"
-
windowPath={path}
-
/>*/}
-
</div>
-
</>
-
)}
-
</Show>
-
);
-
}
+223 -109
src/routes/repo/tree.tsx
···
ShTangledRepoLanguages,
ShTangledRepoTree,
} from "@atcute/tangled";
-
import { type Params, useParams } from "@solidjs/router";
+
import { type Params, useNavigate, useParams } from "@solidjs/router";
import {
createMemo,
createResource,
···
Switch,
} from "solid-js";
import { SolidMarkdown } from "solid-markdown";
-
import { IconWithText } from "../../elements/icon_with_text";
import { languageColors } from "../../util/get_language";
-
import type { RepoLog } from "../../util/types";
+
import type { Branches, RepoLog, Tags } from "../../util/types";
+
import { Header } from "./components/header";
import { useDid } from "./context";
-
import { Header } from "./main";
import {
getRepoBranches,
getRepoDefaultBranch,
getRepoLanguages,
getRepoLog,
+
getRepoTags,
getRepoTree,
} from "./main.data";
import "../../styles/markdown.css";
import { figureOutDid } from "../../util/handle";
+
import { toRelativeTime } from "../../util/time";
+
import { PathBar } from "./components/pathbar";
export async function preloadRepoTree({ params }: { params: Params }) {
-
const did = await figureOutDid(params.user);
+
const did = await figureOutDid(params.user!);
if (!did) return;
-
getRepoTree(did, params.repo, params.ref, params.path);
+
getRepoTree(did, params.repo!, params.ref!, params.path!);
}
export default function RepoTree() {
-
const params = useParams();
+
const navigate = useNavigate();
+
const params = useParams() as {
+
user: string;
+
repo: string;
+
ref: string;
+
path: string;
+
};
const did = useDid();
const [defaultBranch] = createResource(did, async (did) => {
···
const [languages] = createResource(did, async (did) => {
const res = await getRepoLanguages(did, params.repo, params.ref);
if (!res.ok) return;
-
return res.data.languages.sort((a, b) => b.percentage - a.percentage);
+
return res.data.languages.sort((a, b) =>
+
b.name === "" ? -1 : b.percentage - a.percentage,
+
);
});
const [logs] = createResource(
() => {
const d = did();
-
return d && ([d, params.repo, params.ref, params.path] as const);
+
return d && ([d, params.repo, params.ref] as const);
},
-
async ([d, repo, ref, path]) => {
-
const res = await getRepoLog(d, repo, ref, path);
+
async ([d, repo, ref]) => {
+
const res = await getRepoLog(d, repo, ref);
if (!res.ok) return;
return res.data as RepoLog;
},
);
-
const [branchesAndTags] = createResource(
+
const [branches] = createResource(
() => {
const d = did();
return d && ([d, params.repo, params.ref] as const);
},
async ([d, repo, ref]) => {
-
const resBranches = await getRepoBranches(d, repo, ref);
-
if (!resBranches.ok) return;
-
return resBranches.data as RepoLog;
+
const res = await getRepoBranches(d, repo, ref);
+
if (!res.ok) return;
+
return res.data as Branches;
+
},
+
);
+
+
const [tags] = createResource(
+
() => {
+
const d = did();
+
return d && ([d, params.repo, params.ref, params.path] as const);
+
},
+
async ([d, repo, ref, path]) => {
+
if (path) return;
+
const res = await getRepoTags(d, repo, ref);
+
if (!res.ok) return;
+
return res.data as Tags;
},
);
-
const [readme] = createResource(tree, async (tree) => {
-
if (!tree.readme) return;
+
const readme = createMemo(() => {
+
const readme = tree()?.readme;
+
if (!readme) return;
+
return {
-
contents: tree.readme.contents,
-
type: tree.readme.filename.toLowerCase().endsWith(".md")
+
contents: readme.contents,
+
type: readme.filename.toLowerCase().endsWith(".md")
? "markdown"
: "plaintext",
} as const;
});
-
const [filesInOrder] = createResource(tree, (tree) => {
-
if (!tree.files) return;
-
return tree.files.sort((a, b) => {
-
if (!a.is_file === b.is_file) return !a.is_file ? -1 : 1;
+
const sortedFiles = createMemo(() => {
+
const files = tree()?.files;
+
if (!files) return;
+
+
return files.sort((a, b) => {
+
if (a.mode.startsWith("01") !== b.mode.startsWith("01"))
+
return a.mode.startsWith("01") ? 1 : -1;
const aDot = a.name.startsWith(".");
const bDot = b.name.startsWith(".");
···
});
});
-
const repoData = createMemo(() => {
-
const db = defaultBranch();
-
const l = languages();
-
if (!(db && l)) return;
-
return [db, l] as const;
+
const isANonDefaultBranchSelected = createMemo(() => {
+
if (!branches()) return;
+
return (
+
defaultBranch() !== ref() &&
+
Boolean(
+
branches()!.branches.find((branch) => branch.reference.name === ref()),
+
)
+
);
});
-
const pathData = createMemo(() => {
-
const t = tree();
-
const f = filesInOrder();
-
const r = readme();
-
const l = logs();
-
if (!(t && f && r && l)) return;
-
return [t, f, r, l] as const;
-
});
+
const ref = createMemo(() => params.ref || defaultBranch());
return (
<div class="mx-auto max-w-5xl">
-
<Show when={repoData()} keyed>
-
{([defaultBranch, languages]) => (
-
<Show when={pathData()} keyed>
-
{([tree, files, readme, logs]) => (
-
<div>
-
<Header user={params.user} repo={params.repo} />
-
<div class="mb-4 flex flex-col rounded bg-white dark:bg-gray-800">
-
<LanguageLine languages={languages} />
-
<div class="flex flex-row">
-
<div class="mr-1 flex w-1/2 flex-col border-gray-300 border-r p-2 pt-1 dark:border-gray-700">
-
<FileDirectory
-
user={params.user}
-
repo={params.repo}
-
files={files}
-
tree={tree}
-
defaultBranch={defaultBranch}
-
/>
-
</div>
-
<div class="ml-1 flex w-1/2 flex-col p-2 pt-1">
-
<LogData
-
user={params.user}
-
repo={params.repo}
-
defaultBranch={defaultBranch}
-
files={files}
-
logs={logs}
-
/>
-
</div>
-
</div>
+
<div>
+
<Header user={params.user} repo={params.repo} />
+
<div class="mb-4 flex flex-col rounded bg-white dark:bg-gray-800">
+
<Switch>
+
<Match when={!params.path}>
+
<Show when={languages()} fallback={<div class="h-4" />}>
+
<LanguageLine languages={languages()!} />
+
</Show>
+
<div class="flex flex-row px-5 py-2">
+
<Show when={branches() && tags() && ref() && defaultBranch()}>
+
<select
+
class="w-40 border border-gray-200 bg-white p-1 dark:border-gray-700 dark:bg-gray-800"
+
onInput={(e) =>
+
navigate(
+
`/${params.user}/${params.repo}/tree/${e.target.value}`,
+
)
+
}
+
>
+
<Show when={branches()?.branches}>
+
<optgroup
+
label={`branches (${branches()?.branches.length})`}
+
>
+
<Show when={isANonDefaultBranchSelected()}>
+
<option selected>{ref()}</option>
+
</Show>
+
<option selected={ref() === defaultBranch()}>
+
{defaultBranch()}
+
</option>
+
<For each={branches()!.branches}>
+
{(branch) =>
+
branch.reference.name !== ref() &&
+
branch.reference.name !== defaultBranch() && (
+
<option>{branch.reference.name}</option>
+
)
+
}
+
</For>
+
</optgroup>
+
</Show>
+
<Show when={tags()?.tags}>
+
<optgroup label={`tags (${tags()?.tags.length})`}>
+
<For each={tags()!.tags}>
+
{(tag) => (
+
<option selected={tag.name === ref()}>
+
{tag.name}
+
</option>
+
)}
+
</For>
+
</optgroup>
+
</Show>
+
</select>
+
</Show>
+
</div>
+
<div class="flex flex-row py-2">
+
<div class="flex flex-1 flex-col border-gray-300 px-5 md:mr-1 md:w-1/2 md:border-r md:pr-3 dark:border-gray-700">
+
<Show when={defaultBranch() && tree() && sortedFiles()}>
+
<FileDirectory
+
user={params.user}
+
repo={params.repo}
+
files={sortedFiles()!}
+
tree={tree()!}
+
defaultBranch={defaultBranch()!}
+
/>
+
</Show>
</div>
-
<Show when={readme.contents}>
-
<ReadmeCard
-
path={`/${params.user}/${params.repo}/blob/${tree.ref || defaultBranch}`}
-
readme={readme}
+
<div class="flex w-1/2 flex-col pr-5 pl-2 max-md:hidden">
+
<Show when={defaultBranch() && sortedFiles() && logs()}>
+
<LogData
+
user={params.user}
+
repo={params.repo}
+
defaultBranch={defaultBranch()!}
+
files={sortedFiles()!}
+
logs={logs()!}
+
/>
+
</Show>
+
</div>
+
</div>
+
</Match>
+
<Match when={params.path && ref()}>
+
<div class="mx-5 flex flex-row border-gray-300 border-b pt-4 pb-2 md:items-center dark:border-gray-700">
+
<PathBar
+
user={params.user}
+
repo={params.repo}
+
gitref={ref()!}
+
path={params.path}
+
is_file={false}
+
/>
+
</div>
+
<div class="flex flex-row px-5 py-2">
+
<Show when={defaultBranch() && tree() && sortedFiles()}>
+
<FileDirectory
+
user={params.user}
+
repo={params.repo}
+
files={sortedFiles()!}
+
tree={tree()!}
+
defaultBranch={defaultBranch()!}
/>
</Show>
</div>
-
)}
-
</Show>
-
)}
-
</Show>
+
</Match>
+
</Switch>
+
</div>
+
<Show when={readme()?.contents}>
+
<ReadmeCard
+
path={`/${params.user}/${params.repo}/blob/${tree()!.ref || defaultBranch}`}
+
readme={readme()!}
+
/>
+
</Show>
+
</div>
</div>
);
}
···
};
}) {
return (
-
<div class="mb-4 rounded bg-white p-4 dark:bg-gray-800">
+
<div class="rounded bg-white p-4 dark:bg-gray-800">
<Switch>
<Match when={props.readme.type === "markdown"}>
<SolidMarkdown
···
return (
<div class={languageLineState() ? "h-full" : "h-4"}>
-
<div
+
<button
+
type="button"
class={`flex w-full flex-row overflow-hidden rounded-t duration-75 hover:h-4 ${languageLineState() ? "h-4" : "h-2"}`}
-
onclick={toggleLanguageLineState}
+
onClick={toggleLanguageLineState}
>
<For each={props.languages}>
{(language) => (
<div
-
class="h-full border-gray-50 border-r duration-75 hover:brightness-90 dark:border-gray-950 dark:hover:brightness-110"
-
style={`width: ${language.percentage}%; background-color: ${languageColors.get(language.name.toLowerCase().replaceAll(" ", ""))}`}
+
class="h-full border-gray-50 not-last:border-r duration-75 hover:brightness-90 dark:border-gray-950 dark:hover:brightness-110"
+
style={`width: ${language.percentage}%; background-color: ${languageColors.get(language.name.toLowerCase().replaceAll(" ", "")) ?? "aaa"}`}
title={`${language.name} ${language.percentage}%`}
></div>
)}
</For>
-
</div>
+
</button>
<div
-
class={`flex h-4 flex-row gap-3 border-gray-300 border-r border-b px-6 py-3.5 text-xs dark:border-gray-700 ${languageLineState() ? "" : "hidden"}`}
+
class={`flex h-4 flex-row justify-around gap-3 border-gray-300 border-b px-6 py-3.5 text-xs dark:border-gray-700 ${languageLineState() ? "" : "hidden"}`}
>
<For each={props.languages}>
{(language) => (
<div class="flex flex-row items-center gap-2">
<div
class="h-2 w-2 rounded-full"
-
style={`background-color: ${languageColors.get(language.name.toLowerCase().replaceAll(" ", ""))}`}
+
style={`background-color: ${languageColors.get(language.name.toLowerCase().replaceAll(" ", "")) ?? "#aaa"}`}
/>
<span>
-
<span>{language.name}</span>{" "}
+
<span>{language.name || "Other"}</span>{" "}
<span class="text-gray-600 dark:text-gray-400">
{language.percentage}%
</span>
···
defaultBranch: string;
}) {
return (
-
<div class="flex w-full flex-col">
-
<Show when={props.tree.parent}>
-
<a
-
href={`/${props.user}/${props.repo}/tree/${props.tree.ref}/${props.tree.dotdot ? `/${props.tree.dotdot}` : ""}`}
-
class="flex flex-row items-center gap-1 p-1 hover:underline"
-
>
-
<div class="iconify gravity-ui--folder-open-fill" />
-
<span>..</span>
-
</a>
-
</Show>
-
+
<div class="@container flex w-full flex-col">
<For each={props.files}>
-
{(file) => (
-
<a
-
href={`/${props.user}/${props.repo}/${file.is_file ? "blob" : "tree"}/${props.tree.ref || props.defaultBranch}/${props.tree.parent ? `${props.tree.parent}/` : ""}${file.name}`}
-
class="flex flex-row items-center gap-1 p-1 hover:underline"
-
>
-
<div
-
class={`iconify ${file.is_file ? "gravity-ui--file" : "gravity-ui--folder-fill"}`}
-
/>
-
<span>{file.name}</span>
-
</a>
-
)}
+
{(file) => {
+
const is_file = file.mode.startsWith("01");
+
const last_commit_date =
+
file.last_commit && new Date(file.last_commit.when);
+
return (
+
<div class="flex flex-row justify-between">
+
<a
+
href={`/${props.user}/${props.repo}/${is_file ? "blob" : "tree"}/${props.tree.ref || props.defaultBranch}/${props.tree.parent ? `${props.tree.parent}/` : ""}${file.name}`}
+
class="flex flex-1 @max-xl:grow flex-row items-center gap-1.5 truncate p-1 hover:underline"
+
>
+
<div
+
class={`iconify ${is_file ? "gravity-ui--file" : "gravity-ui--folder-fill"}`}
+
/>
+
<span>{file.name}</span>
+
</a>
+
<Show when={last_commit_date}>
+
<a
+
href={`/${props.user}/${props.repo}/commit/${file.last_commit!.hash}`}
+
class="mr-2 @max-xl:hidden min-w-0 flex-1 grow truncate text-ellipsis text-left text-gray-500 hover:text-gray-700 hover:underline dark:text-gray-400 hover:dark:text-gray-200"
+
>
+
{file.last_commit!.message}
+
</a>
+
<a
+
href={`/${props.user}/${props.repo}/commit/${file.last_commit!.hash}`}
+
title={last_commit_date!.toLocaleString(undefined, {
+
dateStyle: "full",
+
timeStyle: "short",
+
})}
+
class="shrink-0 whitespace-nowrap text-gray-500 text-xs hover:text-gray-700 hover:underline dark:text-gray-400 hover:dark:text-gray-200"
+
>
+
{toRelativeTime(last_commit_date!)}
+
</a>
+
</Show>
+
</div>
+
);
+
}}
</For>
</div>
);
···
class="mb-2 flex flex-row items-center gap-2 text-black hover:text-gray-600 dark:text-white hover:dark:text-gray-300"
href={`/${props.user}/${props.repo}/commits/${props.logs.ref || props.defaultBranch}`}
>
-
<IconWithText
-
icon="gravity-ui--code-commit"
-
text="commits"
-
style="font-bold"
-
/>
+
<div class="flex select-none flex-row items-center gap-1 font-bold">
+
<div class="iconify gravity-ui--code-commit" />
+
<span>commits</span>
+
</div>
<div class="rounded bg-gray-300 px-1 text-xs dark:bg-gray-700">
{props.logs.total}
</div>
···
const hash = commit.Hash.map((num) =>
num.toString(16).padStart(2, "0"),
).join("");
+
const date = new Date(commit.Author.When);
+
return (
<div class="flex flex-col gap-1">
<a
···
<span class="select-none px-1 before:content-['\00B7']" />
<span>{commit.Author.Name}</span>
<span class="select-none px-1 before:content-['\00B7']" />
-
<span>{`${new Date(commit.Author.When).toLocaleDateString(undefined, { dateStyle: "short" })} at ${new Date(commit.Author.When).toLocaleTimeString()}`}</span>
+
<span
+
title={date.toLocaleString(undefined, {
+
dateStyle: "full",
+
timeStyle: "short",
+
})}
+
>{`${toRelativeTime(date)}`}</span>
</span>
</div>
);
-86
src/styles/fileviewer.css
···
-
@import "tailwindcss";
-
-
pre code .line-wrapper {
-
@apply flex flex-row;
-
}
-
-
pre code .line-number {
-
@apply opacity-50 shrink-0 w-12 text-right pr-4 select-none;
-
}
-
-
pre code .line-content {
-
@apply flex-1 pl-4 whitespace-pre-wrap text-sm;
-
}
-
-
.hljs {
-
@apply text-gray-900 dark:text-gray-300;
-
}
-
.hljs-doctag,
-
.hljs-keyword,
-
.hljs-meta .hljs-keyword,
-
.hljs-template-tag,
-
.hljs-template-variable,
-
.hljs-type,
-
.hljs-variable.language_ {
-
@apply text-red-700 dark:text-red-400;
-
}
-
.hljs-title,
-
.hljs-title.class_,
-
.hljs-title.class_.inherited__,
-
.hljs-title.function_ {
-
@apply text-purple-700 dark:text-purple-400;
-
}
-
.hljs-attr,
-
.hljs-attribute,
-
.hljs-literal,
-
.hljs-meta,
-
.hljs-number,
-
.hljs-operator,
-
.hljs-variable,
-
.hljs-selector-attr,
-
.hljs-selector-class,
-
.hljs-selector-id {
-
@apply text-blue-700 dark:text-blue-400;
-
}
-
.hljs-regexp,
-
.hljs-string,
-
.hljs-meta .hljs-string {
-
@apply text-cyan-800 dark:text-cyan-300;
-
}
-
.hljs-built_in,
-
.hljs-symbol {
-
@apply text-amber-700 dark:text-amber-400;
-
}
-
.hljs-comment,
-
.hljs-code,
-
.hljs-formula,
-
pre code .line::before {
-
@apply text-neutral-500 dark:text-neutral-500;
-
}
-
.hljs-name,
-
.hljs-quote,
-
.hljs-selector-tag,
-
.hljs-selector-pseudo {
-
@apply text-green-700 dark:text-green-400;
-
}
-
.hljs-subst {
-
@apply text-neutral-800 dark:text-neutral-300;
-
}
-
.hljs-section {
-
@apply font-bold text-blue-700 dark:text-blue-400;
-
}
-
.hljs-bullet {
-
@apply text-yellow-900 dark:text-yellow-300;
-
}
-
.hljs-emphasis {
-
@apply italic text-gray-900 dark:text-gray-400;
-
}
-
.hljs-strong {
-
@apply font-bold text-gray-900 dark:text-gray-400;
-
}
-
.hljs-addition {
-
@apply bg-green-100 text-green-700 dark:bg-green-800/30 dark:text-green-400;
-
}
-
.hljs-deletion {
-
@apply bg-red-100 text-red-700 dark:bg-red-800/30 dark:text-red-400;
-
}
+7 -62
src/styles/index.css
···
@import "tailwindcss";
-
@import "../../static/fonts/inter/inter";
-
@import "../../static/fonts/ibm-plex-mono/ibm-plex-mono";
+
@import "../../static/fonts/inter/inter.css";
+
@import "../../static/fonts/ibm-plex-mono/ibm-plex-mono.css";
@plugin "@iconify/tailwind4" {
/* biome-ignore lint/correctness/noUnknownProperty: this works dude idk how to set it properly */
···
:root {
--font-sans: "InterVariable", ui-sans-serif, sans-serif;
-
--mono-font: "IBM Plex Mono", ui-monospace, monospace;
+
--font-mono: "IBM Plex Mono", ui-monospace, monospace;
}
@supports (font-variation-settings: normal) {
···
}
}
-
.btn {
-
@apply relative z-10 inline-flex min-h-[30px] items-center justify-center bg-transparent pl-2 pr-2 text-sm text-gray-900 outline-none;
+
@utility btn {
+
@apply relative z-10 inline-flex min-h-[30px] cursor-pointer items-center justify-center bg-transparent px-2 pb-[0.2rem] text-sm text-gray-900 before:absolute before:inset-0 before:-z-10 before:block before:rounded before:border before:border-gray-200 before:bg-white before:shadow-[inset_0_-2px_0_0_rgba(0,0,0,0.1),0_1px_0_0_rgba(0,0,0,0.04)] before:content-[''] before:transition-all before:duration-150 before:ease-in-out hover:before:shadow-[inset_0_-2px_0_0_rgba(0,0,0,0.15),0_2px_1px_0_rgba(0,0,0,0.06)] hover:before:bg-gray-50 dark:hover:before:bg-gray-700 active:before:shadow-[inset_0_2px_2px_0_rgba(0,0,0,0.1)] focus:outline-none focus-visible:before:outline-2 focus-visible:before:outline-gray-400 disabled:cursor-not-allowed disabled:opacity-50 dark:text-gray-100 dark:before:bg-gray-800 dark:before:border-gray-700;
}
-
.btn::before {
-
@apply absolute inset-0 -z-10 rounded border border-gray-200 bg-white duration-150 transition-all ease-in;
-
--tw-shadow:
-
inset 0 -2px 0 0 rgba(0, 0, 0, 0.1), 0 1px 0 0 rgba(0, 0, 0, 0.04);
-
--tw-shadow-colored:
-
inset 0 -2px 0 0 var(--tw-shadow-color), 0 1px 0 0 var(--tw-shadow-color);
-
box-shadow:
-
var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
-
var(--tw-shadow);
-
content: "";
-
}
-
-
.btn:hover::before {
-
@apply bg-gray-50;
-
--tw-shadow:
-
inset 0 -2px 0 0 rgba(0, 0, 0, 0.15), 0 2px 1px 0 rgba(0, 0, 0, 0.06);
-
--tw-shadow-colored:
-
inset 0 -2px 0 0 var(--tw-shadow-color), 0 2px 1px 0 var(--tw-shadow-color);
-
box-shadow:
-
var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
-
var(--tw-shadow);
-
content: "";
-
}
-
-
.btn:focus {
-
@apply outline-2 outline-offset-2;
-
}
-
-
.btn:focus-visible::before {
-
@apply outline-solid outline-2 outline-gray-400;
-
}
-
-
.btn:active::before {
-
--tw-shadow: inset 0 2px 2px 0 rgba(0, 0, 0, 0.1);
-
--tw-shadow-colored: inset 0 2px 2px 0 var(--tw-shadow-color);
-
box-shadow:
-
var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
-
var(--tw-shadow);
-
content: "";
-
}
-
-
.btn:disabled {
-
@apply cursor-not-allowed opacity-50;
-
}
-
-
@media (prefers-color-scheme: dark) {
-
.btn {
-
@apply text-gray-100;
-
}
-
-
.btn::before {
-
@apply border-gray-700 bg-gray-800;
-
}
-
-
.btn:hover::before {
-
@apply bg-gray-700;
-
}
+
@utility btn-create {
+
@apply btn text-white before:bg-green-600 hover:before:bg-green-700 dark:before:bg-green-700 dark:hover:before:bg-green-800 before:border before:border-green-700 hover:before:border-green-800 focus-visible:before:outline-green-500 disabled:before:bg-green-400 dark:disabled:before:bg-green-600;
}
+16
src/util/bytes.ts
···
+
export function formatBytes(bytes: number): string {
+
if (bytes === 0) return "0 B";
+
+
const k = 1000; // Use 1000 for "kB", use 1024 if you want "KiB" math
+
const sizes = ["B", "kB", "MB", "GB", "TB", "PB"];
+
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
+
const value = bytes / k ** i;
+
+
// 1. toFixed(1) ensures we don't have crazy long decimals (1.33333 -> "1.3")
+
// 2. parseFloat() strips useless zeros ("1.0" -> 1, "1.5" -> 1.5)
+
// 3. i === 0 check ensures simple Bytes are always integers
+
const formattedValue = i === 0 ? value : parseFloat(value.toFixed(1));
+
+
return `${formattedValue} ${sizes[i]}`;
+
}
+25 -3
src/util/get_repo.ts
···
"user_repos",
);
-
export const getUserRepo = async (
+
export const getUserRepoByRkey = query(
+
async (did: DID, rkey: string): Promise<ShTangledRepo.Main | undefined> => {
+
const pds = await getUserPDS(did);
+
if (!pds) return;
+
const handler = simpleFetchHandler({ service: pds });
+
const rpc = new Client({ handler });
+
+
const { ok, data } = await rpc.get("com.atproto.repo.getRecord", {
+
params: {
+
repo: did,
+
collection: "sh.tangled.repo",
+
rkey,
+
},
+
});
+
+
if (!ok) return;
+
+
return data.value as ShTangledRepo.Main;
+
},
+
"user_repos",
+
);
+
+
export async function getUserRepo(
did: DID,
repo: string,
-
): Promise<ShTangledRepo.Main & { rkey: string }> => {
+
): Promise<ShTangledRepo.Main & { rkey: string }> {
const repos = await getUserRepos(did);
return repos[repo];
-
};
+
}
export const getRepoKnot = async (did: DID, repo: string) => {
const repos = await getUserRepos(did);
+42 -14
src/util/handle.ts
···
import {
+
CompositeDidDocumentResolver,
CompositeHandleResolver,
DohJsonHandleResolver,
+
PlcDidDocumentResolver,
+
WebDidDocumentResolver,
WellKnownHandleResolver,
} from "@atcute/identity-resolver";
import { query } from "@solidjs/router";
···
},
});
-
export const figureOutDid = query(async (user: string): Promise<DID> => {
-
const isDid = user.startsWith("did:");
-
if (!isDid && user.includes(".")) {
-
let did = didMap.get(user);
-
if (!did && useSlingshot) {
-
const res = await fetch(
-
`${slingshotUrl}/xrpc/com.atproto.identity.resolveHandle?handle=${user}`,
-
);
-
if (res.ok) {
-
const json = await res.json();
-
if ("did" in json && typeof json.did === "string") did = json.did;
+
const docResolver = new CompositeDidDocumentResolver({
+
methods: {
+
plc: new PlcDidDocumentResolver(),
+
web: new WebDidDocumentResolver(),
+
},
+
});
+
+
export const figureOutDid = query(async (handle: string): Promise<DID> => {
+
const isDid = handle.startsWith("did:");
+
if (!isDid && handle.includes(".")) {
+
let did = didMap.get(handle);
+
// if (!did && useSlingshot) {
+
// const res = await fetch(
+
// `${slingshotUrl}/xrpc/com.atproto.identity.resolveHandle?handle=${handle}`,
+
// );
+
// if (res.ok) {
+
// const json = await res.json();
+
// if ("did" in json && typeof json.did === "string") did = json.did;
+
// }
+
// }
+
if (!did) {
+
try {
+
did = await handleResolver.resolve(handle as `${string}.${string}`);
+
} catch {
+
did = "did:plc:fail";
}
}
-
if (!did) did = await handleResolver.resolve(user as `${string}.${string}`);
-
didMap.set(user, did);
+
didMap.set(handle, did);
return did;
}
-
return user as DID;
+
return handle as DID;
+
}, "did");
+
+
export const figureOutHandle = query(async (did: DID): Promise<string> => {
+
try {
+
const doc = await docResolver.resolve(did);
+
if (doc.alsoKnownAs?.[0]) {
+
const handle = doc.alsoKnownAs[0].replace("at://", "");
+
didMap.set(handle, did);
+
return handle;
+
}
+
} catch {}
+
return did;
}, "handles");
+33
src/util/time.ts
···
+
// this was gemini
+
export function toRelativeTime(date: Date) {
+
const now = Date.now();
+
const diffInSeconds = Math.floor((now - date.getTime()) / 1000);
+
+
// Use Math.abs to handle future dates (optional, but good practice)
+
const seconds = Math.abs(diffInSeconds);
+
+
// Define units in descending order.
+
// We added 'week' to match your screenshot style.
+
const units = [
+
{ label: "year", seconds: 31536000 },
+
{ label: "month", seconds: 2592000 }, // ~30 days
+
{ label: "week", seconds: 604800 }, // 7 days
+
{ label: "day", seconds: 86400 },
+
{ label: "hour", seconds: 3600 },
+
{ label: "minute", seconds: 60 },
+
{ label: "second", seconds: 1 },
+
];
+
+
for (const { label, seconds: unitSeconds } of units) {
+
// We use floor because 13 days is generally considered "1 week ago", not "2 weeks ago"
+
const interval = Math.floor(seconds / unitSeconds);
+
+
if (interval >= 1) {
+
const suffix = interval === 1 ? "" : "s";
+
const action = diffInSeconds < 0 ? "from now" : "ago";
+
return `${interval} ${label}${suffix} ${action}`;
+
}
+
}
+
+
return "just now";
+
}
+99
src/util/types.ts
···
}[];
};
};
+
+
export type Compare = {
+
rev1: string;
+
rev2: string;
+
format_patch?: {
+
Files?: {
+
OldName: string;
+
NewName: string;
+
IsNew: boolean;
+
IsDelete: boolean;
+
IsCopy: boolean;
+
IsRename: boolean;
+
OldMode: number;
+
NewMode: number;
+
OldOIDPrefix: string;
+
NewOIDPrefix: string;
+
Score: number;
+
TextFragments?: DiffTextFragment[];
+
}[];
+
SHA: string;
+
Author: { Name: string; Email: string };
+
AuthorDate: string;
+
Commiter: string | null;
+
CommiterDate: string;
+
Title: string;
+
Body: string;
+
SubjectPrefix: string;
+
BodyAppendix: string;
+
}[];
+
combined_patch?: {
+
OldName: string;
+
NewName: string;
+
IsNew: boolean;
+
IsDelete: boolean;
+
IsCopy: boolean;
+
IsRename: boolean;
+
OldMode: number;
+
NewMode: number;
+
OldOIDPrefix: string;
+
NewOIDPrefix: string;
+
Score: number;
+
TextFragments?: DiffTextFragment[];
+
IsBinary: boolean;
+
BinaryFragment: string | null;
+
ReverseBinaryFragment: string | null;
+
}[];
+
combined_patch_raw: string;
+
};
+
+
export type Branches = {
+
branches: {
+
reference: {
+
name: string;
+
hash: string;
+
};
+
commit: {
+
Hash: number[];
+
Author: {
+
Name: string;
+
Email: string;
+
When: string;
+
};
+
Committer: {
+
Name: string;
+
Email: string;
+
When: string;
+
};
+
MergeTag: string;
+
PGPSignature: string;
+
Message: string;
+
TreeHash: number[];
+
ParentHashes: number[][];
+
Encoding: string;
+
ExtraHeaders: null;
+
};
+
is_default: boolean;
+
}[];
+
};
+
+
export type Tags = {
+
tags: {
+
name: string;
+
hash: string;
+
tag: {
+
Hash: number[];
+
Name: string;
+
Tagger: {
+
Name: string;
+
Email: string;
+
When: string;
+
};
+
Message: string;
+
PGPSignature: string;
+
TargetType: number;
+
Target: number[];
+
};
+
message: string;
+
}[];
+
};
+16 -35
static/fonts/ibm-plex-mono/ibm-plex-mono.css
···
src:
local("IBM Plex Mono Bold"),
local("IBMPlexMono-Bold"),
-
url("../fonts/complete/woff2/IBMPlexMono-Bold.woff2") format("woff2"),
-
url("../fonts/complete/woff/IBMPlexMono-Bold.woff") format("woff");
+
url("./IBMPlexMono-Bold.woff2") format("woff2");
}
@font-face {
font-family: "IBM Plex Mono";
···
src:
local("IBM Plex Mono Bold Italic"),
local("IBMPlexMono-BoldItalic"),
-
url("../fonts/complete/woff2/IBMPlexMono-BoldItalic.woff2") format("woff2"),
-
url("../fonts/complete/woff/IBMPlexMono-BoldItalic.woff") format("woff");
+
url("./IBMPlexMono-BoldItalic.woff2") format("woff2");
}
@font-face {
font-family: "IBM Plex Mono";
···
src:
local("IBM Plex Mono ExtraLight"),
local("IBMPlexMono-ExtraLight"),
-
url("../fonts/complete/woff2/IBMPlexMono-ExtraLight.woff2") format("woff2"),
-
url("../fonts/complete/woff/IBMPlexMono-ExtraLight.woff") format("woff");
+
url("./IBMPlexMono-ExtraLight.woff2") format("woff2");
}
@font-face {
font-family: "IBM Plex Mono";
···
src:
local("IBM Plex Mono ExtraLight Italic"),
local("IBMPlexMono-ExtraLightItalic"),
-
url("../fonts/complete/woff2/IBMPlexMono-ExtraLightItalic.woff2")
-
format("woff2"),
-
url("../fonts/complete/woff/IBMPlexMono-ExtraLightItalic.woff")
-
format("woff");
+
url("./IBMPlexMono-ExtraLightItalic.woff2") format("woff2");
}
@font-face {
font-family: "IBM Plex Mono";
···
src:
local("IBM Plex Mono Italic"),
local("IBMPlexMono-Italic"),
-
url("../fonts/complete/woff2/IBMPlexMono-Italic.woff2") format("woff2"),
-
url("../fonts/complete/woff/IBMPlexMono-Italic.woff") format("woff");
+
url("./IBMPlexMono-Italic.woff2") format("woff2");
}
@font-face {
font-family: "IBM Plex Mono";
···
src:
local("IBM Plex Mono Light"),
local("IBMPlexMono-Light"),
-
url("../fonts/complete/woff2/IBMPlexMono-Light.woff2") format("woff2"),
-
url("../fonts/complete/woff/IBMPlexMono-Light.woff") format("woff");
+
url("./IBMPlexMono-Light.woff2") format("woff2");
}
@font-face {
font-family: "IBM Plex Mono";
···
src:
local("IBM Plex Mono Light Italic"),
local("IBMPlexMono-LightItalic"),
-
url("../fonts/complete/woff2/IBMPlexMono-LightItalic.woff2") format("woff2"),;
+
url("./IBMPlexMono-LightItalic.woff2") format("woff2");
}
@font-face {
font-family: "IBM Plex Mono";
···
src:
local("IBM Plex Mono Medium"),
local("IBMPlexMono-Medium"),
-
url("../fonts/complete/woff2/IBMPlexMono-Medium.woff2") format("woff2"),
-
url("../fonts/complete/woff/IBMPlexMono-Medium.woff") format("woff");
+
url("./IBMPlexMono-Medium.woff2") format("woff2");
}
@font-face {
font-family: "IBM Plex Mono";
···
src:
local("IBM Plex Mono Medium Italic"),
local("IBMPlexMono-MediumItalic"),
-
url("../fonts/complete/woff2/IBMPlexMono-MediumItalic.woff2")
-
format("woff2"),
-
url("../fonts/complete/woff/IBMPlexMono-MediumItalic.woff") format("woff");
+
url("./IBMPlexMono-MediumItalic.woff2") format("woff2");
}
@font-face {
font-family: "IBM Plex Mono";
···
src:
local("IBM Plex Mono"),
local("IBMPlexMono"),
-
url("../fonts/complete/woff2/IBMPlexMono-Regular.woff2") format("woff2"),
-
url("../fonts/complete/woff/IBMPlexMono-Regular.woff") format("woff");
+
url("./IBMPlexMono-Regular.woff2") format("woff2");
}
@font-face {
font-family: "IBM Plex Mono";
···
src:
local("IBM Plex Mono SemiBold"),
local("IBMPlexMono-SemiBold"),
-
url("../fonts/complete/woff2/IBMPlexMono-SemiBold.woff2") format("woff2"),
-
url("../fonts/complete/woff/IBMPlexMono-SemiBold.woff") format("woff");
+
url("./IBMPlexMono-SemiBold.woff2") format("woff2");
}
@font-face {
font-family: "IBM Plex Mono";
···
src:
local("IBM Plex Mono SemiBold Italic"),
local("IBMPlexMono-SemiBoldItalic"),
-
url("../fonts/complete/woff2/IBMPlexMono-SemiBoldItalic.woff2")
-
format("woff2"),
-
url("../fonts/complete/woff/IBMPlexMono-SemiBoldItalic.woff") format("woff");
+
url("./IBMPlexMono-SemiBoldItalic.woff2") format("woff2");
}
@font-face {
font-family: "IBM Plex Mono";
···
src:
local("IBM Plex Mono Text"),
local("IBMPlexMono-Text"),
-
url("../fonts/complete/woff2/IBMPlexMono-Text.woff2") format("woff2"),
-
url("../fonts/complete/woff/IBMPlexMono-Text.woff") format("woff");
+
url("./IBMPlexMono-Text.woff2") format("woff2");
}
@font-face {
font-family: "IBM Plex Mono";
···
src:
local("IBM Plex Mono Text Italic"),
local("IBMPlexMono-TextItalic"),
-
url("../fonts/complete/woff2/IBMPlexMono-TextItalic.woff2") format("woff2"),
-
url("../fonts/complete/woff/IBMPlexMono-TextItalic.woff") format("woff");
+
url("./IBMPlexMono-TextItalic.woff2") format("woff2");
}
@font-face {
font-family: "IBM Plex Mono";
···
src:
local("IBM Plex Mono Thin"),
local("IBMPlexMono-Thin"),
-
url("../fonts/complete/woff2/IBMPlexMono-Thin.woff2") format("woff2"),
-
url("../fonts/complete/woff/IBMPlexMono-Thin.woff") format("woff");
+
url("./IBMPlexMono-Thin.woff2") format("woff2");
}
@font-face {
font-family: "IBM Plex Mono";
···
src:
local("IBM Plex Mono Thin Italic"),
local("IBMPlexMono-ThinItalic"),
-
url("../fonts/complete/woff2/IBMPlexMono-ThinItalic.woff2") format("woff2"),
-
url("../fonts/complete/woff/IBMPlexMono-ThinItalic.woff") format("woff");
+
url("./IBMPlexMono-ThinItalic.woff2") format("woff2");
}
+7 -1
tsconfig.json
···
// Type Checking & Safety
"strict": true,
-
"types": ["vite/client", "solid-js", "@atcute/tangled", "@atcute/atproto"]
+
"types": [
+
"vite/client",
+
"solid-js",
+
"@atcute/tangled",
+
"@atcute/atproto",
+
"@atcute/microcosm"
+
]
}
}
+1 -1
vite.config.ts
···
export default defineConfig({
plugins: [devtools(), solidPlugin(), tailwindcss()],
server: {
-
port: 3000,
+
port: 3067,
},
build: {
target: "esnext",