diff --git a/bun.lock b/bun.lock
index 2168ecf..5979935 100644
--- a/bun.lock
+++ b/bun.lock
@@ -6,20 +6,20 @@
"name": "hostinfo",
"dependencies": {
"@heroicons/react": "^2.2.0",
- "@tailwindcss/vite": "^4.1.18",
+ "@tailwindcss/vite": "^4.2.1",
"clsx": "^2.1.1",
"react": "^19.2.4",
"react-dom": "^19.2.4",
- "tailwind-merge": "^3.4.0",
- "tailwindcss": "^4.1.18",
+ "tailwind-merge": "^3.5.0",
+ "tailwindcss": "^4.2.1",
},
"devDependencies": {
- "@types/chrome": "^0.1.36",
- "@types/react": "^19.2.10",
+ "@types/chrome": "^0.1.37",
+ "@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@wxt-dev/module-react": "^1.1.5",
"typescript": "^5.9.3",
- "wxt": "^0.20.13",
+ "wxt": "^0.20.18",
},
},
},
@@ -128,10 +128,6 @@
"@heroicons/react": ["@heroicons/react@2.2.0", "", { "peerDependencies": { "react": ">= 16 || ^19.0.0-rc" } }, "sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ=="],
- "@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="],
-
- "@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="],
-
"@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.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
@@ -206,35 +202,35 @@
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.57.1", "", { "os": "win32", "cpu": "x64" }, "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA=="],
- "@tailwindcss/node": ["@tailwindcss/node@4.1.18", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.6.1", "lightningcss": "1.30.2", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.1.18" } }, "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ=="],
+ "@tailwindcss/node": ["@tailwindcss/node@4.2.1", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.19.0", "jiti": "^2.6.1", "lightningcss": "1.31.1", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.2.1" } }, "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg=="],
- "@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.18", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.18", "@tailwindcss/oxide-darwin-arm64": "4.1.18", "@tailwindcss/oxide-darwin-x64": "4.1.18", "@tailwindcss/oxide-freebsd-x64": "4.1.18", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", "@tailwindcss/oxide-linux-x64-musl": "4.1.18", "@tailwindcss/oxide-wasm32-wasi": "4.1.18", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" } }, "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A=="],
+ "@tailwindcss/oxide": ["@tailwindcss/oxide@4.2.1", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.2.1", "@tailwindcss/oxide-darwin-arm64": "4.2.1", "@tailwindcss/oxide-darwin-x64": "4.2.1", "@tailwindcss/oxide-freebsd-x64": "4.2.1", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", "@tailwindcss/oxide-linux-x64-musl": "4.2.1", "@tailwindcss/oxide-wasm32-wasi": "4.2.1", "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" } }, "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw=="],
- "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.18", "", { "os": "android", "cpu": "arm64" }, "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q=="],
+ "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.2.1", "", { "os": "android", "cpu": "arm64" }, "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg=="],
- "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.18", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A=="],
+ "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.2.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw=="],
- "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.18", "", { "os": "darwin", "cpu": "x64" }, "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw=="],
+ "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.2.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw=="],
- "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.18", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA=="],
+ "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.2.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA=="],
- "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18", "", { "os": "linux", "cpu": "arm" }, "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA=="],
+ "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1", "", { "os": "linux", "cpu": "arm" }, "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw=="],
- "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.18", "", { "os": "linux", "cpu": "arm64" }, "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw=="],
+ "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ=="],
- "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.18", "", { "os": "linux", "cpu": "arm64" }, "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg=="],
+ "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ=="],
- "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.18", "", { "os": "linux", "cpu": "x64" }, "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g=="],
+ "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g=="],
- "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.18", "", { "os": "linux", "cpu": "x64" }, "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ=="],
+ "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g=="],
- "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.18", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.1.0", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.4.0" }, "cpu": "none" }, "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA=="],
+ "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.2.1", "", { "dependencies": { "@emnapi/core": "^1.8.1", "@emnapi/runtime": "^1.8.1", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.1.1", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.8.1" }, "cpu": "none" }, "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q=="],
- "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.18", "", { "os": "win32", "cpu": "arm64" }, "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA=="],
+ "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.2.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA=="],
- "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.18", "", { "os": "win32", "cpu": "x64" }, "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q=="],
+ "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.2.1", "", { "os": "win32", "cpu": "x64" }, "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ=="],
- "@tailwindcss/vite": ["@tailwindcss/vite@4.1.18", "", { "dependencies": { "@tailwindcss/node": "4.1.18", "@tailwindcss/oxide": "4.1.18", "tailwindcss": "4.1.18" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA=="],
+ "@tailwindcss/vite": ["@tailwindcss/vite@4.2.1", "", { "dependencies": { "@tailwindcss/node": "4.2.1", "@tailwindcss/oxide": "4.2.1", "tailwindcss": "4.2.1" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w=="],
"@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=="],
@@ -244,7 +240,7 @@
"@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
- "@types/chrome": ["@types/chrome@0.1.36", "", { "dependencies": { "@types/filesystem": "*", "@types/har-format": "*" } }, "sha512-BvHbuyGttYXnGt5Gpwa4769KIinKHY1iLjlAPrrMBS2GI9m/XNMPtdsq0NgQalyuUdxvlMN/0OyGw0shFVIoUQ=="],
+ "@types/chrome": ["@types/chrome@0.1.37", "", { "dependencies": { "@types/filesystem": "*", "@types/har-format": "*" } }, "sha512-IJE4ceuDO7lrEuua7Pow47zwNcI8E6qqkowRP7aFPaZ0lrjxh6y836OPqqkIZeTX64FTogbw+4RNH0+QrweCTQ=="],
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
@@ -258,7 +254,7 @@
"@types/node": ["@types/node@25.2.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w=="],
- "@types/react": ["@types/react@19.2.10", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw=="],
+ "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
"@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
@@ -270,7 +266,7 @@
"@webext-core/match-patterns": ["@webext-core/match-patterns@1.0.3", "", {}, "sha512-NY39ACqCxdKBmHgw361M9pfJma8e4AZo20w9AY+5ZjIj1W2dvXC8J31G5fjfOGbulW9w4WKpT8fPooi0mLkn9A=="],
- "@wxt-dev/browser": ["@wxt-dev/browser@0.1.32", "", { "dependencies": { "@types/filesystem": "*", "@types/har-format": "*" } }, "sha512-jvfSppeLzlH4sOkIvMBJoA1pKoI+U5gTkjDwMKdkTWh0P/fj+KDyze3lzo3S6372viCm8tXUKNez+VKyVz2ZDw=="],
+ "@wxt-dev/browser": ["@wxt-dev/browser@0.1.37", "", { "dependencies": { "@types/filesystem": "*", "@types/har-format": "*" } }, "sha512-I32XWCNRy2W6UgbaVXz8BHGBGtm8urGRRBrcNLagUBXTrBi7wCE6zWePUvvK+nUl7qUCZ7iQ1ufdP0c1DEWisw=="],
"@wxt-dev/module-react": ["@wxt-dev/module-react@1.1.5", "", { "dependencies": { "@vitejs/plugin-react": "^4.4.1 || ^5.0.0" }, "peerDependencies": { "wxt": ">=0.19.16" } }, "sha512-KgsUrsgH5rBT8MwiipnDEOHBXmLvTIdFICrI7KjngqSf9DpVRn92HsKmToxY0AYpkP19hHWta2oNYFTzmmm++g=="],
@@ -300,7 +296,7 @@
"atomically": ["atomically@2.1.0", "", { "dependencies": { "stubborn-fs": "^2.0.0", "when-exit": "^2.1.4" } }, "sha512-+gDffFXRW6sl/HCwbta7zK4uNqbPjv4YJEAdz7Vu+FLQHe77eZ4bvbJGi4hE0QPeJlMYMA3piXEr1UL3dAwx7Q=="],
- "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
+ "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
"baseline-browser-mapping": ["baseline-browser-mapping@2.9.19", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg=="],
@@ -310,7 +306,7 @@
"boxen": ["boxen@8.0.1", "", { "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^8.0.0", "chalk": "^5.3.0", "cli-boxes": "^3.0.0", "string-width": "^7.2.0", "type-fest": "^4.21.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0" } }, "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw=="],
- "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
+ "brace-expansion": ["brace-expansion@5.0.3", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA=="],
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
@@ -330,7 +326,7 @@
"chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
- "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
+ "chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="],
"chrome-launcher": ["chrome-launcher@1.2.0", "", { "dependencies": { "@types/node": "*", "escape-string-regexp": "^4.0.0", "is-wsl": "^2.2.0", "lighthouse-logger": "^2.0.1" }, "bin": { "print-chrome-path": "bin/print-chrome-path.cjs" } }, "sha512-JbuGuBNss258bvGil7FT4HKdC3SC2K7UAEUqiPy3ACS3Yxo3hAW6bvFpCu2HsIJLgTqxgEX6BkujvzZfLpUD0Q=="],
@@ -342,7 +338,7 @@
"cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="],
- "cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="],
+ "cli-spinners": ["cli-spinners@3.4.0", "", {}, "sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw=="],
"cli-truncate": ["cli-truncate@4.0.0", "", { "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^7.0.0" } }, "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA=="],
@@ -412,15 +408,15 @@
"dot-prop": ["dot-prop@9.0.0", "", { "dependencies": { "type-fest": "^4.18.2" } }, "sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ=="],
- "dotenv": ["dotenv@17.2.3", "", {}, "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w=="],
+ "dotenv": ["dotenv@17.3.1", "", {}, "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA=="],
"dotenv-expand": ["dotenv-expand@12.0.3", "", { "dependencies": { "dotenv": "^16.4.5" } }, "sha512-uc47g4b+4k/M/SeaW1y4OApx+mtLWl92l5LMPP0GNXctZqELk+YGgOPIIC5elYmUH4OuoK3JLhuRUYegeySiFA=="],
"electron-to-chromium": ["electron-to-chromium@1.5.283", "", {}, "sha512-3vifjt1HgrGW/h76UEeny+adYApveS9dH2h3p57JYzBSXJIKUJAvtmIytDKjcSCt9xHfrNCFJ7gts6vkhuq++w=="],
- "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
+ "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
- "enhanced-resolve": ["enhanced-resolve@5.18.4", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q=="],
+ "enhanced-resolve": ["enhanced-resolve@5.19.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg=="],
"entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="],
@@ -474,7 +470,7 @@
"get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
- "get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
+ "get-east-asian-width": ["get-east-asian-width@1.5.0", "", {}, "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA=="],
"get-port-please": ["get-port-please@3.2.0", "", {}, "sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A=="],
@@ -492,7 +488,7 @@
"growly": ["growly@1.3.0", "", {}, "sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw=="],
- "hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="],
+ "hookable": ["hookable@6.0.1", "", {}, "sha512-uKGyY8BuzN/a5gvzvA+3FVWo0+wUjgtfSdnmjtrOVwQCZPHpHDH2WRO3VZSOeluYrHoDCiXFffZXs8Dj1ULWtw=="],
"html-escaper": ["html-escaper@3.0.3", "", {}, "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ=="],
@@ -520,6 +516,8 @@
"is-in-ci": ["is-in-ci@1.0.0", "", { "bin": { "is-in-ci": "cli.js" } }, "sha512-eUuAjybVTHMYWm/U+vBO1sY/JOCgoPCXRxzdju0K+K0BiGW0SChEL1MLC0PoCIR1OlPo5YAp8HuQoUlsWEICwg=="],
+ "is-in-ssh": ["is-in-ssh@1.0.0", "", {}, "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw=="],
+
"is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="],
"is-installed-globally": ["is-installed-globally@1.0.0", "", { "dependencies": { "global-directory": "^4.0.1", "is-path-inside": "^4.0.0" } }, "sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ=="],
@@ -608,7 +606,7 @@
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
- "log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="],
+ "log-symbols": ["log-symbols@7.0.1", "", { "dependencies": { "is-unicode-supported": "^2.0.0", "yoctocolors": "^2.1.1" } }, "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg=="],
"log-update": ["log-update@6.1.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w=="],
@@ -616,7 +614,7 @@
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
- "magicast": ["magicast@0.3.5", "", { "dependencies": { "@babel/parser": "^7.25.4", "@babel/types": "^7.25.4", "source-map-js": "^1.2.0" } }, "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ=="],
+ "magicast": ["magicast@0.5.2", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "source-map-js": "^1.2.1" } }, "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ=="],
"make-error": ["make-error@1.3.6", "", {}, "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="],
@@ -630,7 +628,7 @@
"mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
- "minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="],
+ "minimatch": ["minimatch@10.2.2", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw=="],
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
@@ -640,7 +638,7 @@
"multimatch": ["multimatch@6.0.0", "", { "dependencies": { "@types/minimatch": "^3.0.5", "array-differ": "^4.0.0", "array-union": "^3.0.1", "minimatch": "^3.0.4" } }, "sha512-I7tSVxHGPlmPN/enE3mS1aOSo6bWBfls+3HmuEeCUBCE7gWnm3cBXCBkpurzFjVRwC6Kld8lLaZ1Iv5vOcjvcQ=="],
- "nano-spawn": ["nano-spawn@1.0.3", "", {}, "sha512-jtpsQDetTnvS2Ts1fiRdci5rx0VYws5jGyC+4IYOTnIQ/wwdf6JdomlHBwqC3bJYOvaKu0C2GSZ1A60anrYpaA=="],
+ "nano-spawn": ["nano-spawn@2.0.0", "", {}, "sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw=="],
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
@@ -656,7 +654,7 @@
"nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="],
- "nypm": ["nypm@0.6.4", "", { "dependencies": { "citty": "^0.2.0", "pathe": "^2.0.3", "tinyexec": "^1.0.2" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-1TvCKjZyyklN+JJj2TS3P4uSQEInrM/HkkuSXsEzm1ApPgBffOn8gFguNnZf07r/1X6vlryfIqMUkJKQMzlZiw=="],
+ "nypm": ["nypm@0.6.5", "", { "dependencies": { "citty": "^0.2.0", "pathe": "^2.0.3", "tinyexec": "^1.0.2" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ=="],
"obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="],
@@ -668,9 +666,9 @@
"onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="],
- "open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="],
+ "open": ["open@11.0.0", "", { "dependencies": { "default-browser": "^5.4.0", "define-lazy-prop": "^3.0.0", "is-in-ssh": "^1.0.0", "is-inside-container": "^1.0.0", "powershell-utils": "^0.1.0", "wsl-utils": "^0.3.0" } }, "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw=="],
- "ora": ["ora@8.2.0", "", { "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", "stdin-discarder": "^0.2.2", "string-width": "^7.2.0", "strip-ansi": "^7.1.0" } }, "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw=="],
+ "ora": ["ora@9.3.0", "", { "dependencies": { "chalk": "^5.6.2", "cli-cursor": "^5.0.0", "cli-spinners": "^3.2.0", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.1.0", "log-symbols": "^7.0.1", "stdin-discarder": "^0.3.1", "string-width": "^8.1.0" } }, "sha512-lBX72MWFduWEf7v7uWf5DHp9Jn5BI8bNPGuFgtXMmr2uDz2Gz2749y3am3agSDdkhHPHYmmxEGSKH85ZLGzgXw=="],
"os-shim": ["os-shim@0.1.3", "", {}, "sha512-jd0cvB8qQ5uVt0lvCIexBaROw1KyKm5sbulg2fWOHjETisuCzWyt+eTZKEMs8v6HwzoGs8xik26jg7eCM6pS+A=="],
@@ -698,6 +696,8 @@
"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=="],
+ "powershell-utils": ["powershell-utils@0.1.0", "", {}, "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A=="],
+
"process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="],
"process-warning": ["process-warning@5.0.0", "", {}, "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA=="],
@@ -730,7 +730,7 @@
"readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
- "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
+ "readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="],
"real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="],
@@ -792,9 +792,9 @@
"split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="],
- "stdin-discarder": ["stdin-discarder@0.2.2", "", {}, "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ=="],
+ "stdin-discarder": ["stdin-discarder@0.3.1", "", {}, "sha512-reExS1kSGoElkextOcPkel4NE99S0BWxjUHQeDFnR8S993JxpPX7KU4MNmO19NXhlJp+8dmdCbKQVNgLJh2teA=="],
- "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
+ "string-width": ["string-width@8.2.0", "", { "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } }, "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw=="],
"string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
@@ -810,9 +810,9 @@
"stubborn-utils": ["stubborn-utils@1.0.2", "", {}, "sha512-zOh9jPYI+xrNOyisSelgym4tolKTJCQd5GBhK0+0xJvcYDcwlOoxF/rnFKQ2KRZknXSG9jWAp66fwP6AxN9STg=="],
- "tailwind-merge": ["tailwind-merge@3.4.0", "", {}, "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g=="],
+ "tailwind-merge": ["tailwind-merge@3.5.0", "", {}, "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A=="],
- "tailwindcss": ["tailwindcss@4.1.18", "", {}, "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw=="],
+ "tailwindcss": ["tailwindcss@4.2.1", "", {}, "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw=="],
"tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
@@ -880,9 +880,9 @@
"wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
- "wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="],
+ "wsl-utils": ["wsl-utils@0.3.1", "", { "dependencies": { "is-wsl": "^3.1.0", "powershell-utils": "^0.1.0" } }, "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg=="],
- "wxt": ["wxt@0.20.13", "", { "dependencies": { "@1natsu/wait-element": "^4.1.2", "@aklinker1/rollup-plugin-visualizer": "5.12.0", "@webext-core/fake-browser": "^1.3.2", "@webext-core/isolated-element": "^1.1.2", "@webext-core/match-patterns": "^1.0.3", "@wxt-dev/browser": "^0.1.32", "@wxt-dev/storage": "^1.0.0", "async-mutex": "^0.5.0", "c12": "^3.3.2", "cac": "^6.7.14", "chokidar": "^4.0.3", "ci-info": "^4.3.1", "consola": "^3.4.2", "defu": "^6.1.4", "dotenv": "^17.2.3", "dotenv-expand": "^12.0.3", "esbuild": "^0.27.1", "fast-glob": "^3.3.3", "filesize": "^11.0.13", "fs-extra": "^11.3.2", "get-port-please": "^3.2.0", "giget": "^1.2.3 || ^2.0.0", "hookable": "^5.5.3", "import-meta-resolve": "^4.2.0", "is-wsl": "^3.1.0", "json5": "^2.2.3", "jszip": "^3.10.1", "linkedom": "^0.18.12", "magicast": "^0.3.5", "minimatch": "^10.1.1", "nano-spawn": "^1.0.3", "normalize-path": "^3.0.0", "nypm": "^0.6.2", "ohash": "^2.0.11", "open": "^10.2.0", "ora": "^8.2.0", "perfect-debounce": "^2.0.0", "picocolors": "^1.1.1", "prompts": "^2.4.2", "publish-browser-extension": "^2.3.0 || ^3.0.2", "scule": "^1.3.0", "unimport": "^3.13.1 || ^4.0.0 || ^5.0.0", "vite": "^5.4.19 || ^6.3.4 || ^7.0.0", "vite-node": "^3.2.4 || ^5.0.0", "web-ext-run": "^0.2.4" }, "bin": { "wxt": "bin/wxt.mjs", "wxt-publish-extension": "bin/wxt-publish-extension.cjs" } }, "sha512-FwQEk+0a4/pYha6rTKGl5iicU6kRYDBDiElJf55CFEfoJKqvGzBTZpphafurQfqU1X0hvAm9w5GEWC0thXI6wQ=="],
+ "wxt": ["wxt@0.20.18", "", { "dependencies": { "@1natsu/wait-element": "^4.1.2", "@aklinker1/rollup-plugin-visualizer": "5.12.0", "@webext-core/fake-browser": "^1.3.4", "@webext-core/isolated-element": "^1.1.3", "@webext-core/match-patterns": "^1.0.3", "@wxt-dev/browser": "^0.1.37", "@wxt-dev/storage": "^1.0.0", "async-mutex": "^0.5.0", "c12": "^3.3.3", "cac": "^6.7.14", "chokidar": "^5.0.0", "ci-info": "^4.4.0", "consola": "^3.4.2", "defu": "^6.1.4", "dotenv": "^17.2.4", "dotenv-expand": "^12.0.3", "esbuild": "^0.27.1", "fast-glob": "^3.3.3", "filesize": "^11.0.13", "fs-extra": "^11.3.3", "get-port-please": "^3.2.0", "giget": "^1.2.3 || ^2.0.0 || ^3.0.0", "hookable": "^6.0.1", "import-meta-resolve": "^4.2.0", "is-wsl": "^3.1.0", "json5": "^2.2.3", "jszip": "^3.10.1", "linkedom": "^0.18.12", "magicast": "^0.5.2", "minimatch": "^10.1.2", "nano-spawn": "^2.0.0", "normalize-path": "^3.0.0", "nypm": "^0.6.5", "ohash": "^2.0.11", "open": "^11.0.0", "ora": "^9.3.0", "perfect-debounce": "^2.1.0", "picocolors": "^1.1.1", "prompts": "^2.4.2", "publish-browser-extension": "^2.3.0 || ^3.0.2 || ^4.0.4", "scule": "^1.3.0", "unimport": "^3.13.1 || ^4.0.0 || ^5.0.0", "vite": "^5.4.19 || ^6.3.4 || ^7.0.0", "vite-node": "^3.2.4 || ^5.0.0", "web-ext-run": "^0.2.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" }, "optionalPeers": ["eslint"], "bin": { "wxt": "bin/wxt.mjs", "wxt-publish-extension": "bin/wxt-publish-extension.mjs" } }, "sha512-BYnIAFkdJcC8BXzbh4PzmRhOQ5xKELEk45qntzqojW5X1+VGm0GsjaEKSCQnTP72/3jZMDH1pmlEdkY/fPXehg=="],
"xdg-basedir": ["xdg-basedir@5.1.0", "", {}, "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ=="],
@@ -898,6 +898,8 @@
"yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
+ "yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="],
+
"zip-dir": ["zip-dir@2.0.0", "", { "dependencies": { "async": "^3.2.0", "jszip": "^3.2.2" } }, "sha512-uhlsJZWz26FLYXOD6WVuq+fIcZ3aBPGo/cFdiLlv3KNwpa52IF3ISV8fLhQLiqVu5No3VhlqlgthN6gehil1Dg=="],
"zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="],
@@ -908,6 +910,8 @@
"@pnpm/network.ca-file/graceful-fs": ["graceful-fs@4.2.10", "", {}, "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="],
+ "@tailwindcss/node/lightningcss": ["lightningcss@1.31.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.31.1", "lightningcss-darwin-arm64": "1.31.1", "lightningcss-darwin-x64": "1.31.1", "lightningcss-freebsd-x64": "1.31.1", "lightningcss-linux-arm-gnueabihf": "1.31.1", "lightningcss-linux-arm64-gnu": "1.31.1", "lightningcss-linux-arm64-musl": "1.31.1", "lightningcss-linux-x64-gnu": "1.31.1", "lightningcss-linux-x64-musl": "1.31.1", "lightningcss-win32-arm64-msvc": "1.31.1", "lightningcss-win32-x64-msvc": "1.31.1" } }, "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ=="],
+
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
@@ -920,16 +924,22 @@
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
+ "@wxt-dev/storage/@wxt-dev/browser": ["@wxt-dev/browser@0.1.32", "", { "dependencies": { "@types/filesystem": "*", "@types/har-format": "*" } }, "sha512-jvfSppeLzlH4sOkIvMBJoA1pKoI+U5gTkjDwMKdkTWh0P/fj+KDyze3lzo3S6372viCm8tXUKNez+VKyVz2ZDw=="],
+
"ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
+ "boxen/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
+
"boxen/type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
- "c12/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="],
+ "c12/dotenv": ["dotenv@17.2.3", "", {}, "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w=="],
"chrome-launcher/escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
"chrome-launcher/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="],
+ "cli-truncate/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
+
"cliui/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
@@ -946,14 +956,14 @@
"fx-runner/commander": ["commander@2.9.0", "", { "dependencies": { "graceful-readlink": ">= 1.0.0" } }, "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A=="],
+ "giget/nypm": ["nypm@0.6.4", "", { "dependencies": { "citty": "^0.2.0", "pathe": "^2.0.3", "tinyexec": "^1.0.2" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-1TvCKjZyyklN+JJj2TS3P4uSQEInrM/HkkuSXsEzm1ApPgBffOn8gFguNnZf07r/1X6vlryfIqMUkJKQMzlZiw=="],
+
"global-directory/ini": ["ini@4.1.1", "", {}, "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g=="],
"is-inside-container/is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],
"lighthouse-logger/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
- "log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="],
-
"log-update/slice-ansi": ["slice-ansi@7.1.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w=="],
"mlly/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=="],
@@ -970,6 +980,8 @@
"package-json/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
+ "publish-browser-extension/dotenv": ["dotenv@17.2.3", "", {}, "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w=="],
+
"rc/ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
"rc/strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="],
@@ -990,36 +1002,78 @@
"vite/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
+ "widest-line/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
+
+ "wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
+
"yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"@aklinker1/rollup-plugin-visualizer/open/define-lazy-prop": ["define-lazy-prop@2.0.0", "", {}, "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="],
"@aklinker1/rollup-plugin-visualizer/open/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="],
- "ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
+ "@tailwindcss/node/lightningcss/lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="],
+
+ "@tailwindcss/node/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="],
+
+ "@tailwindcss/node/lightningcss/lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.31.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA=="],
+
+ "@tailwindcss/node/lightningcss/lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.31.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A=="],
+
+ "@tailwindcss/node/lightningcss/lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.31.1", "", { "os": "linux", "cpu": "arm" }, "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g=="],
+
+ "@tailwindcss/node/lightningcss/lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg=="],
+
+ "@tailwindcss/node/lightningcss/lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg=="],
+
+ "@tailwindcss/node/lightningcss/lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA=="],
+
+ "@tailwindcss/node/lightningcss/lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA=="],
+
+ "@tailwindcss/node/lightningcss/lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.31.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w=="],
+
+ "@tailwindcss/node/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.31.1", "", { "os": "win32", "cpu": "x64" }, "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw=="],
"ansi-align/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
- "c12/chokidar/readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="],
+ "boxen/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
- "cliui/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
+ "boxen/string-width/get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
+
+ "cli-truncate/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
+
+ "cli-truncate/string-width/get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
"cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"cliui/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
+ "giget/nypm/citty": ["citty@0.2.0", "", {}, "sha512-8csy5IBFI2ex2hTVpaHN2j+LNE199AgiI7y4dMintrr8i0lQiFn+0AWMZrWdHKIgMOer65f8IThysYhoReqjWA=="],
+
"log-update/slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="],
"mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="],
+ "multimatch/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
+
"node-notifier/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
- "yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
+ "widest-line/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
+
+ "widest-line/string-width/get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
+
+ "wrap-ansi/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
+
+ "wrap-ansi/string-width/get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
"yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"ansi-align/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
+ "log-update/slice-ansi/is-fullwidth-code-point/get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
+
+ "multimatch/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
+
"yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
}
}
diff --git a/components/Browser.tsx b/components/Browser.tsx
index 5bd7289..6a06809 100644
--- a/components/Browser.tsx
+++ b/components/Browser.tsx
@@ -1,15 +1,11 @@
import { CpuChipIcon, GlobeAltIcon } from '@heroicons/react/24/outline';
import { Header } from './Header';
import { InfoRow } from './Info';
-import type { HostInfo } from '@/utils/types';
-export const BrowserResourceView = ({ data }: { data: HostInfo }) => {
+export const BrowserResourceView = ({ url }: { url: string }) => {
return (
-
+
{
diff --git a/components/CopyButton.tsx b/components/CopyButton.tsx
index 104094c..369ee8b 100644
--- a/components/CopyButton.tsx
+++ b/components/CopyButton.tsx
@@ -1,4 +1,3 @@
-import { useState } from 'react';
import { CheckIcon, ClipboardDocumentIcon } from '@heroicons/react/24/outline';
export const CopyButton = ({ text }: { text: string }) => {
diff --git a/components/Header.tsx b/components/Header.tsx
index 3ebcb6c..d5c9122 100644
--- a/components/Header.tsx
+++ b/components/Header.tsx
@@ -1,10 +1,8 @@
-import { browser } from 'wxt/browser';
-
export const Header = ({ title, flagCode }: { title: string, flagCode?: string | null }) => {
const getFlagUrl = (code?: string | null) => {
if (!code) return '';
try {
- const path = `/${code.toLowerCase()}.webp`;
+ const path = `/${code.toLowerCase()}.png`;
return browser.runtime.getURL(path as any);
} catch {
return '';
diff --git a/components/Local.tsx b/components/Local.tsx
index 8a7d2b5..6da2bcc 100644
--- a/components/Local.tsx
+++ b/components/Local.tsx
@@ -1,13 +1,13 @@
import { CpuChipIcon, ServerIcon } from '@heroicons/react/24/outline';
import { Header } from './Header';
import { InfoRow } from './Info';
-import type { HostInfo } from '@/utils/types';
+import type { GeoData } from '@/utils/types';
-export const LocalNetworkView = ({ data }: { data: HostInfo }) => {
+export const LocalNetworkView = ({ data, domain }: { data: GeoData, domain: string }) => {
return (
@@ -20,7 +20,7 @@ export const LocalNetworkView = ({ data }: { data: HostInfo }) => {
diff --git a/components/Public.tsx b/components/Public.tsx
index 0049302..8885446 100644
--- a/components/Public.tsx
+++ b/components/Public.tsx
@@ -1,59 +1,50 @@
-import {
- ServerIcon,
- MapPinIcon,
- GlobeAltIcon,
- BuildingOfficeIcon
-} from '@heroicons/react/24/outline';
+import { ServerIcon, MapPinIcon, GlobeAltIcon, BuildingOfficeIcon } from '@heroicons/react/24/outline';
import { Header } from './Header';
import { InfoRow } from './Info';
-import type { HostInfo } from '@/utils/types';
-
-export const PublicNetworkView = ({ data }: { data: HostInfo }) => {
- const { network, location, domain } = data;
-
- if (!network) return null;
+import type { GeoData } from '@/utils/types';
+export const PublicNetworkView = ({ data, domain }: { data: GeoData, domain: string }) => {
return (
;
+ if (state.status === 'error') {
+ return
;
}
- // Fallback if network data is missing
- if (!network) {
- return
;
+ if (state.status === 'success' && !state.data) {
+ return
;
}
- // Local Network View
- if (network.isLocal) {
- return
;
+ if (state.status === 'loading' || !state.data) {
+ return (
+
+
+
Analyzing Network...
+
+ );
}
- // Public Internet View
- return
;
+ if (state.data.isLocal || state.data.isBogon) {
+ return
;
+ }
+
+ return
;
}
diff --git a/entrypoints/background.ts b/entrypoints/background.ts
index 95f65df..8d1ec61 100644
--- a/entrypoints/background.ts
+++ b/entrypoints/background.ts
@@ -1,51 +1,253 @@
-import { browser } from 'wxt/browser';
-import { Tab } from '@/services/tab';
import { StorageService } from '@/utils/storage';
+import { GeoService } from '@/services/geo';
+import { IconService } from '@/services/icon';
+import { DnsService } from '@/services/dns';
+
+const SYSTEM_PROTOCOLS = [
+ 'chrome:', 'about:', 'edge:', 'moz-extension:',
+ 'chrome-extension:', 'file:', 'view-source:', 'data:', 'devtools:'
+];
+
+const tabStates = new Map
();
+
+function getDomain(url: string) {
+ try {
+ return new URL(url).hostname;
+ } catch {
+ return url;
+ }
+}
+
+function applyIconForState(tabId: number, state: TabState) {
+ const isSystem = SYSTEM_PROTOCOLS.some(p => state.url.startsWith(p));
+ if (isSystem) {
+ IconService.updateIcon(tabId, null, true);
+ } else if (state.status === 'success' && state.data) {
+ let code = state.data.countryCode;
+ if (state.data.asn === 'AS13335') code = 'cloudflare';
+ IconService.updateIcon(tabId, code, state.data.isLocal);
+ } else {
+ IconService.updateIcon(tabId, null, false);
+ }
+}
+
+async function initTab(tabId: number, url: string, resolveDns = false) {
+ if (!url) return;
+ const isSystem = SYSTEM_PROTOCOLS.some(p => url.startsWith(p));
+ const domain = getDomain(url);
+
+ let currentState = tabStates.get(tabId);
+
+ if (!currentState || currentState.url !== url) {
+ tabStates.set(tabId, {
+ url,
+ domain,
+ status: 'loading',
+ data: null,
+ errorMessage: null,
+ lastUpdated: Date.now()
+ });
+ }
+
+ if (!currentState) {
+ currentState = await StorageService.getTabState(tabId) || undefined;
+ }
+
+ const latestState = tabStates.get(tabId);
+ if (latestState && latestState.url !== url) return;
+ if (latestState && latestState.status === 'success' && latestState.data) return;
+
+ const isSameDomain = currentState?.domain === domain;
+ const hasExistingData = isSameDomain && !!currentState?.data;
+
+ const newState: TabState = {
+ url,
+ domain,
+ status: isSystem || hasExistingData ? 'success' : 'loading',
+ data: hasExistingData ? currentState!.data : null,
+ errorMessage: null,
+ lastUpdated: Date.now()
+ };
+
+ tabStates.set(tabId, newState);
+ StorageService.setTabState(tabId, newState).catch(() => { });
+
+ applyIconForState(tabId, newState);
+
+ if (!isSystem && !hasExistingData && resolveDns) {
+ const ip = await DnsService.resolve(domain);
+ if (ip) {
+ await processIp(tabId, url, ip);
+ } else {
+ await updateState(tabId, {
+ status: 'error',
+ errorMessage: 'Could not resolve host'
+ });
+ }
+ }
+}
+
+async function processIp(tabId: number, url: string, ip: string) {
+ let current = tabStates.get(tabId);
+ if (!current) {
+ current = await StorageService.getTabState(tabId) || undefined;
+ }
+
+ const latestState1 = tabStates.get(tabId);
+ if (latestState1) {
+ try {
+ if (new URL(latestState1.url).hostname !== new URL(url).hostname) return;
+ } catch {
+ return;
+ }
+ }
+
+ if (current?.status === 'success' && current.data?.ip === ip) {
+ return;
+ }
+
+ const geoData = await GeoService.getGeoData(ip);
+
+ const stateAfterFetch = tabStates.get(tabId);
+ if (stateAfterFetch) {
+ try {
+ if (new URL(stateAfterFetch.url).hostname !== new URL(url).hostname) return;
+ } catch {
+ return;
+ }
+ }
+
+ const newState: TabState = {
+ url: stateAfterFetch?.url || url,
+ domain: stateAfterFetch?.domain || getDomain(url),
+ status: 'success',
+ data: geoData,
+ errorMessage: null,
+ lastUpdated: Date.now()
+ };
+
+ tabStates.set(tabId, newState);
+ await StorageService.setTabState(tabId, newState);
+
+ applyIconForState(tabId, newState);
+}
+
+async function updateState(tabId: number, updates: Partial) {
+ let current = tabStates.get(tabId);
+ if (!current) {
+ current = await StorageService.getTabState(tabId) || undefined;
+ }
+
+ if (current) {
+ const newState = { ...current, ...updates };
+ tabStates.set(tabId, newState);
+ await StorageService.setTabState(tabId, newState);
+ applyIconForState(tabId, newState);
+ }
+}
export default defineBackground({
main() {
- // Listen for Network Responses
+ browser.webNavigation.onBeforeNavigate.addListener((details) => {
+ if (details.frameId !== 0) return;
+ initTab(details.tabId, details.url, false);
+ });
+
+ browser.webNavigation.onHistoryStateUpdated.addListener((details) => {
+ if (details.frameId !== 0) return;
+ initTab(details.tabId, details.url, true);
+ });
+
+ browser.webNavigation.onCommitted.addListener((details) => {
+ if (details.frameId !== 0) return;
+ const state = tabStates.get(details.tabId);
+ if (state) {
+ applyIconForState(details.tabId, state);
+ }
+ });
+
browser.webRequest.onResponseStarted.addListener(
- async (details) => {
- if (details.tabId === -1 || details.type !== 'main_frame' || !details.ip) return;
- await Tab.process(details.tabId, details.url, details.ip);
- },
- { urls: [''] }
- );
-
- // Listen for Network Errors (DNS, Connection Refused, etc.)
- browser.webRequest.onErrorOccurred.addListener(
- async (details) => {
+ (details) => {
if (details.tabId === -1 || details.type !== 'main_frame') return;
- await Tab.handleError(details.tabId, details.url, details.error);
+ if (details.ip) {
+ processIp(details.tabId, details.url, details.ip);
+ }
},
{ urls: [''] }
);
- // Listen for Navigation
- browser.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
- if (changeInfo.status === 'complete' && tab.url) {
- const urlObj = new URL(tab.url);
- const isSystemPage = ['chrome:', 'about:', 'edge:', 'moz-extension:', 'chrome-extension:', 'file:'].includes(urlObj.protocol);
+ browser.webNavigation.onCompleted.addListener(async (details) => {
+ if (details.frameId !== 0) return;
- if (isSystemPage) {
- await Tab.processSystemPage(tabId);
- } else if (tab.url.startsWith('http')) {
- // We might not have the IP yet if it was cached, so we trigger a process
- // If IP is missing, Tab waits or we can force a HEAD request here
- await Tab.process(tabId, tab.url);
+ const state = tabStates.get(details.tabId);
- // Force connection to ensure webRequest fires if cached
- try {
- await fetch(tab.url, { method: 'HEAD', cache: 'no-store', mode: 'no-cors' });
- } catch { /* ignore */ }
+ if (state) {
+ applyIconForState(details.tabId, state);
+ }
+
+ if (state && state.status === 'loading' && !state.data) {
+ let hostname = '';
+ try {
+ hostname = new URL(details.url).hostname;
+ } catch {
+ return;
+ }
+ const ip = await DnsService.resolve(hostname);
+
+ if (ip) {
+ await processIp(details.tabId, details.url, ip);
+ } else {
+ await updateState(details.tabId, {
+ status: 'error',
+ errorMessage: 'Could not resolve host'
+ });
}
}
});
- // Cleanup
- browser.tabs.onRemoved.addListener(async (tabId) => {
- await StorageService.remove(tabId);
+ browser.webRequest.onErrorOccurred.addListener(
+ async (details) => {
+ if (details.type !== 'main_frame') return;
+ if (details.error === 'net::ERR_ABORTED') return;
+
+ await updateState(details.tabId, {
+ status: 'error',
+ errorMessage: details.error
+ });
+ },
+ { urls: [''] }
+ );
+
+ browser.tabs.onRemoved.addListener((tabId) => {
+ tabStates.delete(tabId);
+ StorageService.removeTabState(tabId);
+ });
+
+ browser.tabs.onActivated.addListener(async (activeInfo) => {
+ const tab = await browser.tabs.get(activeInfo.tabId);
+ if (tab.url) {
+ const state = tabStates.get(tab.id!);
+ if (state) {
+ applyIconForState(tab.id!, state);
+ } else {
+ initTab(tab.id!, tab.url, true);
+ }
+ }
+ });
+
+ browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
+ if (changeInfo.status && tab.url) {
+ const state = tabStates.get(tabId);
+ if (state) {
+ applyIconForState(tabId, state);
+ }
+ }
+ });
+
+ browser.runtime.onMessage.addListener((message) => {
+ if (message.type === 'INIT_TAB' && message.tabId && message.url) {
+ initTab(message.tabId, message.url, true);
+ }
});
},
});
diff --git a/entrypoints/popup/Popup.tsx b/entrypoints/popup/Popup.tsx
index 1a03225..ae03f01 100644
--- a/entrypoints/popup/Popup.tsx
+++ b/entrypoints/popup/Popup.tsx
@@ -7,9 +7,8 @@ export default function Popup() {
if (loading) {
return (
-
+
);
}
@@ -18,9 +17,5 @@ export default function Popup() {
return
;
}
- if (info.error) {
- return
;
- }
-
- return
;
+ return
;
}
diff --git a/entrypoints/popup/index.html b/entrypoints/popup/index.html
index b799c14..5f198ef 100644
--- a/entrypoints/popup/index.html
+++ b/entrypoints/popup/index.html
@@ -4,7 +4,7 @@
Host Info
-
+
diff --git a/hooks/useHostInfo.ts b/hooks/useHostInfo.ts
index 52c745e..7cfec02 100644
--- a/hooks/useHostInfo.ts
+++ b/hooks/useHostInfo.ts
@@ -1,78 +1,46 @@
-import { useState, useEffect } from 'react';
-import { browser } from 'wxt/browser';
-import { StorageService } from '@/utils/storage';
-import { IconService } from '@/services/icon';
-import type { HostInfo } from '@/utils/types';
-
export function useHostInfo() {
- const [info, setInfo] = useState
(null);
+ const [info, setInfo] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
- let unwatch: (() => void) | undefined;
+ let isMounted = true;
- const init = async () => {
- // Get Current Tab
- const [tab] = await browser.tabs.query({ active: true, currentWindow: true });
- if (!tab?.id || !tab?.url) {
- setLoading(false);
- return;
+ const fetchInfo = async () => {
+ try {
+ const [tab] = await browser.tabs.query({ active: true, currentWindow: true });
+ if (!tab?.id) return;
+
+ const data = await StorageService.getTabState(tab.id);
+ if (data) {
+ if (isMounted) {
+ setInfo(data);
+ setLoading(false);
+ }
+ } else {
+ if (tab.url) {
+ await browser.runtime.sendMessage({ type: 'INIT_TAB', tabId: tab.id, url: tab.url });
+ } else {
+ if (isMounted) setLoading(false);
+ }
+ }
+ } catch (e) {
+ if (isMounted) setLoading(false);
}
-
- // Handle System/Browser Pages immediately
- const urlObj = new URL(tab.url);
-
- const systemProtocols = [
- 'chrome:',
- 'about:',
- 'edge:',
- 'moz-extension:',
- 'chrome-extension:',
- 'edge-extension:',
- 'extension:',
- 'file:',
- 'view-source:',
- 'resource:',
- 'blob:',
- 'data:'
- ];
-
- const isSystemPage = systemProtocols.includes(urlObj.protocol);
-
- if (isSystemPage) {
- await IconService.update(tab.id, null, true);
-
- setInfo({
- url: tab.url,
- domain: 'System Resource',
- loading: false,
- error: null,
- network: null,
- location: null,
- isBrowserResource: true
- });
- setLoading(false);
- return;
- }
-
- // Handle Network Pages via Storage
- const key = StorageService.getKey(tab.id);
-
- // Initial Load
- const current = await StorageService.get(tab.id);
- setInfo(current);
- setLoading(false);
-
- // Watch for changes
- unwatch = storage.watch(key, (newValue) => {
- setInfo(newValue);
- });
};
- init();
+ fetchInfo();
+
+ const listener = (changes: any, areaName: string) => {
+ if (areaName === 'session' || areaName === 'local') {
+ fetchInfo();
+ }
+ };
+
+ browser.storage.onChanged.addListener(listener);
return () => {
- if (unwatch) unwatch();
+ isMounted = false;
+ browser.storage.onChanged.removeListener(listener);
};
}, []);
diff --git a/package.json b/package.json
index 8ead80e..9c135e4 100644
--- a/package.json
+++ b/package.json
@@ -16,19 +16,17 @@
},
"dependencies": {
"@heroicons/react": "^2.2.0",
- "@tailwindcss/vite": "^4.1.18",
- "clsx": "^2.1.1",
+ "@tailwindcss/vite": "^4.2.1",
"react": "^19.2.4",
"react-dom": "^19.2.4",
- "tailwind-merge": "^3.4.0",
- "tailwindcss": "^4.1.18"
+ "tailwindcss": "^4.2.1"
},
"devDependencies": {
- "@types/chrome": "^0.1.36",
- "@types/react": "^19.2.10",
+ "@types/chrome": "^0.1.37",
+ "@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@wxt-dev/module-react": "^1.1.5",
"typescript": "^5.9.3",
- "wxt": "^0.20.13"
+ "wxt": "^0.20.18"
}
}
diff --git a/public/ad.png b/public/ad.png
new file mode 100644
index 0000000..f11076c
Binary files /dev/null and b/public/ad.png differ
diff --git a/public/ad.webp b/public/ad.webp
deleted file mode 100644
index b438413..0000000
Binary files a/public/ad.webp and /dev/null differ
diff --git a/public/ae.png b/public/ae.png
new file mode 100644
index 0000000..ebbc7ff
Binary files /dev/null and b/public/ae.png differ
diff --git a/public/ae.webp b/public/ae.webp
deleted file mode 100644
index 8594f03..0000000
Binary files a/public/ae.webp and /dev/null differ
diff --git a/public/af.png b/public/af.png
new file mode 100644
index 0000000..80c24d6
Binary files /dev/null and b/public/af.png differ
diff --git a/public/af.webp b/public/af.webp
deleted file mode 100644
index 08f2611..0000000
Binary files a/public/af.webp and /dev/null differ
diff --git a/public/ag.png b/public/ag.png
new file mode 100644
index 0000000..8aab2e5
Binary files /dev/null and b/public/ag.png differ
diff --git a/public/ag.webp b/public/ag.webp
deleted file mode 100644
index 2985990..0000000
Binary files a/public/ag.webp and /dev/null differ
diff --git a/public/ai.png b/public/ai.png
new file mode 100644
index 0000000..3be749e
Binary files /dev/null and b/public/ai.png differ
diff --git a/public/ai.webp b/public/ai.webp
deleted file mode 100644
index 17b349c..0000000
Binary files a/public/ai.webp and /dev/null differ
diff --git a/public/al.png b/public/al.png
new file mode 100644
index 0000000..36067ed
Binary files /dev/null and b/public/al.png differ
diff --git a/public/al.webp b/public/al.webp
deleted file mode 100644
index aee9f7f..0000000
Binary files a/public/al.webp and /dev/null differ
diff --git a/public/am.png b/public/am.png
new file mode 100644
index 0000000..334726c
Binary files /dev/null and b/public/am.png differ
diff --git a/public/am.webp b/public/am.webp
deleted file mode 100644
index 5131ea1..0000000
Binary files a/public/am.webp and /dev/null differ
diff --git a/public/ao.png b/public/ao.png
new file mode 100644
index 0000000..9eb7424
Binary files /dev/null and b/public/ao.png differ
diff --git a/public/ao.webp b/public/ao.webp
deleted file mode 100644
index 3840ae0..0000000
Binary files a/public/ao.webp and /dev/null differ
diff --git a/public/aq.png b/public/aq.png
new file mode 100644
index 0000000..632aebb
Binary files /dev/null and b/public/aq.png differ
diff --git a/public/aq.webp b/public/aq.webp
deleted file mode 100644
index 387ca03..0000000
Binary files a/public/aq.webp and /dev/null differ
diff --git a/public/ar.png b/public/ar.png
new file mode 100644
index 0000000..69666bb
Binary files /dev/null and b/public/ar.png differ
diff --git a/public/ar.webp b/public/ar.webp
deleted file mode 100644
index a4a00b3..0000000
Binary files a/public/ar.webp and /dev/null differ
diff --git a/public/as.png b/public/as.png
new file mode 100644
index 0000000..209fb2d
Binary files /dev/null and b/public/as.png differ
diff --git a/public/as.webp b/public/as.webp
deleted file mode 100644
index 6a2a4de..0000000
Binary files a/public/as.webp and /dev/null differ
diff --git a/public/at.png b/public/at.png
new file mode 100644
index 0000000..b0a7783
Binary files /dev/null and b/public/at.png differ
diff --git a/public/at.webp b/public/at.webp
deleted file mode 100644
index 9fb8ab2..0000000
Binary files a/public/at.webp and /dev/null differ
diff --git a/public/au.png b/public/au.png
new file mode 100644
index 0000000..bbb86b8
Binary files /dev/null and b/public/au.png differ
diff --git a/public/au.webp b/public/au.webp
deleted file mode 100644
index 42ba965..0000000
Binary files a/public/au.webp and /dev/null differ
diff --git a/public/aw.png b/public/aw.png
new file mode 100644
index 0000000..af8072d
Binary files /dev/null and b/public/aw.png differ
diff --git a/public/aw.webp b/public/aw.webp
deleted file mode 100644
index fc2ef57..0000000
Binary files a/public/aw.webp and /dev/null differ
diff --git a/public/ax.png b/public/ax.png
new file mode 100644
index 0000000..9d86312
Binary files /dev/null and b/public/ax.png differ
diff --git a/public/ax.webp b/public/ax.webp
deleted file mode 100644
index bf6ecfe..0000000
Binary files a/public/ax.webp and /dev/null differ
diff --git a/public/az.png b/public/az.png
new file mode 100644
index 0000000..e594f5b
Binary files /dev/null and b/public/az.png differ
diff --git a/public/az.webp b/public/az.webp
deleted file mode 100644
index 4333163..0000000
Binary files a/public/az.webp and /dev/null differ
diff --git a/public/ba.png b/public/ba.png
new file mode 100644
index 0000000..d619b33
Binary files /dev/null and b/public/ba.png differ
diff --git a/public/ba.webp b/public/ba.webp
deleted file mode 100644
index 2b4d860..0000000
Binary files a/public/ba.webp and /dev/null differ
diff --git a/public/bb.png b/public/bb.png
new file mode 100644
index 0000000..4620e40
Binary files /dev/null and b/public/bb.png differ
diff --git a/public/bb.webp b/public/bb.webp
deleted file mode 100644
index d4783cd..0000000
Binary files a/public/bb.webp and /dev/null differ
diff --git a/public/bd.png b/public/bd.png
new file mode 100644
index 0000000..b897457
Binary files /dev/null and b/public/bd.png differ
diff --git a/public/bd.webp b/public/bd.webp
deleted file mode 100644
index d7596dc..0000000
Binary files a/public/bd.webp and /dev/null differ
diff --git a/public/be.png b/public/be.png
new file mode 100644
index 0000000..609a2fe
Binary files /dev/null and b/public/be.png differ
diff --git a/public/be.webp b/public/be.webp
deleted file mode 100644
index 8c380f3..0000000
Binary files a/public/be.webp and /dev/null differ
diff --git a/public/bf.png b/public/bf.png
new file mode 100644
index 0000000..30a57d2
Binary files /dev/null and b/public/bf.png differ
diff --git a/public/bf.webp b/public/bf.webp
deleted file mode 100644
index 60183da..0000000
Binary files a/public/bf.webp and /dev/null differ
diff --git a/public/bg.png b/public/bg.png
new file mode 100644
index 0000000..3adc290
Binary files /dev/null and b/public/bg.png differ
diff --git a/public/bg.webp b/public/bg.webp
deleted file mode 100644
index 1caa7b7..0000000
Binary files a/public/bg.webp and /dev/null differ
diff --git a/public/bh.png b/public/bh.png
new file mode 100644
index 0000000..1d3c90d
Binary files /dev/null and b/public/bh.png differ
diff --git a/public/bh.webp b/public/bh.webp
deleted file mode 100644
index 57871ad..0000000
Binary files a/public/bh.webp and /dev/null differ
diff --git a/public/bi.png b/public/bi.png
new file mode 100644
index 0000000..5f744a0
Binary files /dev/null and b/public/bi.png differ
diff --git a/public/bi.webp b/public/bi.webp
deleted file mode 100644
index e130a38..0000000
Binary files a/public/bi.webp and /dev/null differ
diff --git a/public/bj.png b/public/bj.png
new file mode 100644
index 0000000..257d0a8
Binary files /dev/null and b/public/bj.png differ
diff --git a/public/bj.webp b/public/bj.webp
deleted file mode 100644
index f3e0c74..0000000
Binary files a/public/bj.webp and /dev/null differ
diff --git a/public/bl.png b/public/bl.png
new file mode 100644
index 0000000..61de3d4
Binary files /dev/null and b/public/bl.png differ
diff --git a/public/bl.webp b/public/bl.webp
deleted file mode 100644
index 3d812dc..0000000
Binary files a/public/bl.webp and /dev/null differ
diff --git a/public/bm.png b/public/bm.png
new file mode 100644
index 0000000..b01e80d
Binary files /dev/null and b/public/bm.png differ
diff --git a/public/bm.webp b/public/bm.webp
deleted file mode 100644
index 4abccce..0000000
Binary files a/public/bm.webp and /dev/null differ
diff --git a/public/bn.png b/public/bn.png
new file mode 100644
index 0000000..2316c1f
Binary files /dev/null and b/public/bn.png differ
diff --git a/public/bn.webp b/public/bn.webp
deleted file mode 100644
index e0304e7..0000000
Binary files a/public/bn.webp and /dev/null differ
diff --git a/public/bo.png b/public/bo.png
new file mode 100644
index 0000000..51ece22
Binary files /dev/null and b/public/bo.png differ
diff --git a/public/bo.webp b/public/bo.webp
deleted file mode 100644
index e4023a5..0000000
Binary files a/public/bo.webp and /dev/null differ
diff --git a/public/bq.png b/public/bq.png
new file mode 100644
index 0000000..688672c
Binary files /dev/null and b/public/bq.png differ
diff --git a/public/bq.webp b/public/bq.webp
deleted file mode 100644
index 1e1eef9..0000000
Binary files a/public/bq.webp and /dev/null differ
diff --git a/public/br.png b/public/br.png
new file mode 100644
index 0000000..e0628d6
Binary files /dev/null and b/public/br.png differ
diff --git a/public/br.webp b/public/br.webp
deleted file mode 100644
index 3d673c5..0000000
Binary files a/public/br.webp and /dev/null differ
diff --git a/public/bs.png b/public/bs.png
new file mode 100644
index 0000000..511c66d
Binary files /dev/null and b/public/bs.png differ
diff --git a/public/bs.webp b/public/bs.webp
deleted file mode 100644
index e0aa762..0000000
Binary files a/public/bs.webp and /dev/null differ
diff --git a/public/bt.png b/public/bt.png
new file mode 100644
index 0000000..247328e
Binary files /dev/null and b/public/bt.png differ
diff --git a/public/bt.webp b/public/bt.webp
deleted file mode 100644
index 16f1963..0000000
Binary files a/public/bt.webp and /dev/null differ
diff --git a/public/bv.png b/public/bv.png
new file mode 100644
index 0000000..4c000e9
Binary files /dev/null and b/public/bv.png differ
diff --git a/public/bv.webp b/public/bv.webp
deleted file mode 100644
index 6c4c93a..0000000
Binary files a/public/bv.webp and /dev/null differ
diff --git a/public/bw.png b/public/bw.png
new file mode 100644
index 0000000..99b8dbb
Binary files /dev/null and b/public/bw.png differ
diff --git a/public/bw.webp b/public/bw.webp
deleted file mode 100644
index 94acd42..0000000
Binary files a/public/bw.webp and /dev/null differ
diff --git a/public/by.png b/public/by.png
new file mode 100644
index 0000000..e2086c0
Binary files /dev/null and b/public/by.png differ
diff --git a/public/by.webp b/public/by.webp
deleted file mode 100644
index 92d10d3..0000000
Binary files a/public/by.webp and /dev/null differ
diff --git a/public/bz.png b/public/bz.png
new file mode 100644
index 0000000..d504d5a
Binary files /dev/null and b/public/bz.png differ
diff --git a/public/bz.webp b/public/bz.webp
deleted file mode 100644
index 7f6c1de..0000000
Binary files a/public/bz.webp and /dev/null differ
diff --git a/public/ca.png b/public/ca.png
new file mode 100644
index 0000000..d42ab58
Binary files /dev/null and b/public/ca.png differ
diff --git a/public/ca.webp b/public/ca.webp
deleted file mode 100644
index b3cc33d..0000000
Binary files a/public/ca.webp and /dev/null differ
diff --git a/public/cc.png b/public/cc.png
new file mode 100644
index 0000000..256fbc3
Binary files /dev/null and b/public/cc.png differ
diff --git a/public/cc.webp b/public/cc.webp
deleted file mode 100644
index bab1833..0000000
Binary files a/public/cc.webp and /dev/null differ
diff --git a/public/cd.png b/public/cd.png
new file mode 100644
index 0000000..a2949d4
Binary files /dev/null and b/public/cd.png differ
diff --git a/public/cd.webp b/public/cd.webp
deleted file mode 100644
index d8846c1..0000000
Binary files a/public/cd.webp and /dev/null differ
diff --git a/public/cf.png b/public/cf.png
new file mode 100644
index 0000000..3a777ab
Binary files /dev/null and b/public/cf.png differ
diff --git a/public/cf.webp b/public/cf.webp
deleted file mode 100644
index afbcfbe..0000000
Binary files a/public/cf.webp and /dev/null differ
diff --git a/public/cg.png b/public/cg.png
new file mode 100644
index 0000000..4b82edb
Binary files /dev/null and b/public/cg.png differ
diff --git a/public/cg.webp b/public/cg.webp
deleted file mode 100644
index 0a458ec..0000000
Binary files a/public/cg.webp and /dev/null differ
diff --git a/public/ch.png b/public/ch.png
new file mode 100644
index 0000000..692e0ff
Binary files /dev/null and b/public/ch.png differ
diff --git a/public/ch.webp b/public/ch.webp
deleted file mode 100644
index b4293e4..0000000
Binary files a/public/ch.webp and /dev/null differ
diff --git a/public/ci.png b/public/ci.png
new file mode 100644
index 0000000..a727ca2
Binary files /dev/null and b/public/ci.png differ
diff --git a/public/ci.webp b/public/ci.webp
deleted file mode 100644
index c0be868..0000000
Binary files a/public/ci.webp and /dev/null differ
diff --git a/public/ck.png b/public/ck.png
new file mode 100644
index 0000000..f239d68
Binary files /dev/null and b/public/ck.png differ
diff --git a/public/ck.webp b/public/ck.webp
deleted file mode 100644
index 5f13dc9..0000000
Binary files a/public/ck.webp and /dev/null differ
diff --git a/public/cl.png b/public/cl.png
new file mode 100644
index 0000000..33d81ef
Binary files /dev/null and b/public/cl.png differ
diff --git a/public/cl.webp b/public/cl.webp
deleted file mode 100644
index 637135b..0000000
Binary files a/public/cl.webp and /dev/null differ
diff --git a/public/cloudflare.png b/public/cloudflare.png
new file mode 100644
index 0000000..8817ca9
Binary files /dev/null and b/public/cloudflare.png differ
diff --git a/public/cloudflare.webp b/public/cloudflare.webp
deleted file mode 100644
index 7ccf944..0000000
Binary files a/public/cloudflare.webp and /dev/null differ
diff --git a/public/cm.png b/public/cm.png
new file mode 100644
index 0000000..f4e8d5e
Binary files /dev/null and b/public/cm.png differ
diff --git a/public/cm.webp b/public/cm.webp
deleted file mode 100644
index 4ed10ae..0000000
Binary files a/public/cm.webp and /dev/null differ
diff --git a/public/cn.png b/public/cn.png
new file mode 100644
index 0000000..71e9cb7
Binary files /dev/null and b/public/cn.png differ
diff --git a/public/cn.webp b/public/cn.webp
deleted file mode 100644
index 7a31c84..0000000
Binary files a/public/cn.webp and /dev/null differ
diff --git a/public/co.png b/public/co.png
new file mode 100644
index 0000000..12f9b01
Binary files /dev/null and b/public/co.png differ
diff --git a/public/co.webp b/public/co.webp
deleted file mode 100644
index cc20121..0000000
Binary files a/public/co.webp and /dev/null differ
diff --git a/public/cr.png b/public/cr.png
new file mode 100644
index 0000000..f0d4d3f
Binary files /dev/null and b/public/cr.png differ
diff --git a/public/cr.webp b/public/cr.webp
deleted file mode 100644
index 3bdcf68..0000000
Binary files a/public/cr.webp and /dev/null differ
diff --git a/public/cu.png b/public/cu.png
new file mode 100644
index 0000000..552a022
Binary files /dev/null and b/public/cu.png differ
diff --git a/public/cu.webp b/public/cu.webp
deleted file mode 100644
index f608eba..0000000
Binary files a/public/cu.webp and /dev/null differ
diff --git a/public/cv.png b/public/cv.png
new file mode 100644
index 0000000..5d30013
Binary files /dev/null and b/public/cv.png differ
diff --git a/public/cv.webp b/public/cv.webp
deleted file mode 100644
index ac98987..0000000
Binary files a/public/cv.webp and /dev/null differ
diff --git a/public/cw.png b/public/cw.png
new file mode 100644
index 0000000..ed991a2
Binary files /dev/null and b/public/cw.png differ
diff --git a/public/cw.webp b/public/cw.webp
deleted file mode 100644
index dab7917..0000000
Binary files a/public/cw.webp and /dev/null differ
diff --git a/public/cx.png b/public/cx.png
new file mode 100644
index 0000000..68d71c7
Binary files /dev/null and b/public/cx.png differ
diff --git a/public/cx.webp b/public/cx.webp
deleted file mode 100644
index ee8427f..0000000
Binary files a/public/cx.webp and /dev/null differ
diff --git a/public/cy.png b/public/cy.png
new file mode 100644
index 0000000..5ee69b4
Binary files /dev/null and b/public/cy.png differ
diff --git a/public/cy.webp b/public/cy.webp
deleted file mode 100644
index 4399ef2..0000000
Binary files a/public/cy.webp and /dev/null differ
diff --git a/public/cz.png b/public/cz.png
new file mode 100644
index 0000000..b209d9e
Binary files /dev/null and b/public/cz.png differ
diff --git a/public/cz.webp b/public/cz.webp
deleted file mode 100644
index 6afd98a..0000000
Binary files a/public/cz.webp and /dev/null differ
diff --git a/public/de.png b/public/de.png
new file mode 100644
index 0000000..5ca14e3
Binary files /dev/null and b/public/de.png differ
diff --git a/public/de.webp b/public/de.webp
deleted file mode 100644
index ada00c4..0000000
Binary files a/public/de.webp and /dev/null differ
diff --git a/public/dj.png b/public/dj.png
new file mode 100644
index 0000000..70acd12
Binary files /dev/null and b/public/dj.png differ
diff --git a/public/dj.webp b/public/dj.webp
deleted file mode 100644
index 175c013..0000000
Binary files a/public/dj.webp and /dev/null differ
diff --git a/public/dk.png b/public/dk.png
new file mode 100644
index 0000000..d0d845a
Binary files /dev/null and b/public/dk.png differ
diff --git a/public/dk.webp b/public/dk.webp
deleted file mode 100644
index 8ee85cc..0000000
Binary files a/public/dk.webp and /dev/null differ
diff --git a/public/dm.png b/public/dm.png
new file mode 100644
index 0000000..e551518
Binary files /dev/null and b/public/dm.png differ
diff --git a/public/dm.webp b/public/dm.webp
deleted file mode 100644
index 3cb5a28..0000000
Binary files a/public/dm.webp and /dev/null differ
diff --git a/public/do.png b/public/do.png
new file mode 100644
index 0000000..17a537c
Binary files /dev/null and b/public/do.png differ
diff --git a/public/do.webp b/public/do.webp
deleted file mode 100644
index 24ed5e1..0000000
Binary files a/public/do.webp and /dev/null differ
diff --git a/public/dz.png b/public/dz.png
new file mode 100644
index 0000000..1f92523
Binary files /dev/null and b/public/dz.png differ
diff --git a/public/dz.webp b/public/dz.webp
deleted file mode 100644
index c5ae81d..0000000
Binary files a/public/dz.webp and /dev/null differ
diff --git a/public/ec.png b/public/ec.png
new file mode 100644
index 0000000..a07960d
Binary files /dev/null and b/public/ec.png differ
diff --git a/public/ec.webp b/public/ec.webp
deleted file mode 100644
index edbffa7..0000000
Binary files a/public/ec.webp and /dev/null differ
diff --git a/public/ee.png b/public/ee.png
new file mode 100644
index 0000000..2f18530
Binary files /dev/null and b/public/ee.png differ
diff --git a/public/ee.webp b/public/ee.webp
deleted file mode 100644
index 5ae790f..0000000
Binary files a/public/ee.webp and /dev/null differ
diff --git a/public/eg.png b/public/eg.png
new file mode 100644
index 0000000..bef43ac
Binary files /dev/null and b/public/eg.png differ
diff --git a/public/eg.webp b/public/eg.webp
deleted file mode 100644
index 148f521..0000000
Binary files a/public/eg.webp and /dev/null differ
diff --git a/public/eh.png b/public/eh.png
new file mode 100644
index 0000000..f31499e
Binary files /dev/null and b/public/eh.png differ
diff --git a/public/eh.webp b/public/eh.webp
deleted file mode 100644
index edb137c..0000000
Binary files a/public/eh.webp and /dev/null differ
diff --git a/public/er.png b/public/er.png
new file mode 100644
index 0000000..076ee71
Binary files /dev/null and b/public/er.png differ
diff --git a/public/er.webp b/public/er.webp
deleted file mode 100644
index 62bca5b..0000000
Binary files a/public/er.webp and /dev/null differ
diff --git a/public/es.png b/public/es.png
new file mode 100644
index 0000000..c1697cb
Binary files /dev/null and b/public/es.png differ
diff --git a/public/es.webp b/public/es.webp
deleted file mode 100644
index a559ff3..0000000
Binary files a/public/es.webp and /dev/null differ
diff --git a/public/et.png b/public/et.png
new file mode 100644
index 0000000..9137dd0
Binary files /dev/null and b/public/et.png differ
diff --git a/public/et.webp b/public/et.webp
deleted file mode 100644
index 1f3a093..0000000
Binary files a/public/et.webp and /dev/null differ
diff --git a/public/fi.png b/public/fi.png
new file mode 100644
index 0000000..28d074a
Binary files /dev/null and b/public/fi.png differ
diff --git a/public/fi.webp b/public/fi.webp
deleted file mode 100644
index 074ee8b..0000000
Binary files a/public/fi.webp and /dev/null differ
diff --git a/public/fj.png b/public/fj.png
new file mode 100644
index 0000000..d9c4000
Binary files /dev/null and b/public/fj.png differ
diff --git a/public/fj.webp b/public/fj.webp
deleted file mode 100644
index c48effe..0000000
Binary files a/public/fj.webp and /dev/null differ
diff --git a/public/fk.png b/public/fk.png
new file mode 100644
index 0000000..7ede023
Binary files /dev/null and b/public/fk.png differ
diff --git a/public/fk.webp b/public/fk.webp
deleted file mode 100644
index b975dea..0000000
Binary files a/public/fk.webp and /dev/null differ
diff --git a/public/fm.png b/public/fm.png
new file mode 100644
index 0000000..b953212
Binary files /dev/null and b/public/fm.png differ
diff --git a/public/fm.webp b/public/fm.webp
deleted file mode 100644
index 6fb571f..0000000
Binary files a/public/fm.webp and /dev/null differ
diff --git a/public/fo.png b/public/fo.png
new file mode 100644
index 0000000..93b4713
Binary files /dev/null and b/public/fo.png differ
diff --git a/public/fo.webp b/public/fo.webp
deleted file mode 100644
index 93a2cb5..0000000
Binary files a/public/fo.webp and /dev/null differ
diff --git a/public/fr.png b/public/fr.png
new file mode 100644
index 0000000..e258e6a
Binary files /dev/null and b/public/fr.png differ
diff --git a/public/fr.webp b/public/fr.webp
deleted file mode 100644
index bb0eb17..0000000
Binary files a/public/fr.webp and /dev/null differ
diff --git a/public/ga.png b/public/ga.png
new file mode 100644
index 0000000..5610fd6
Binary files /dev/null and b/public/ga.png differ
diff --git a/public/ga.webp b/public/ga.webp
deleted file mode 100644
index 1a2c128..0000000
Binary files a/public/ga.webp and /dev/null differ
diff --git a/public/gb-eng.png b/public/gb-eng.png
new file mode 100644
index 0000000..8520032
Binary files /dev/null and b/public/gb-eng.png differ
diff --git a/public/gb-eng.webp b/public/gb-eng.webp
deleted file mode 100644
index c55b61b..0000000
Binary files a/public/gb-eng.webp and /dev/null differ
diff --git a/public/gb-nir.png b/public/gb-nir.png
new file mode 100644
index 0000000..a70fead
Binary files /dev/null and b/public/gb-nir.png differ
diff --git a/public/gb-nir.webp b/public/gb-nir.webp
deleted file mode 100644
index 2050ba9..0000000
Binary files a/public/gb-nir.webp and /dev/null differ
diff --git a/public/gb-sct.png b/public/gb-sct.png
new file mode 100644
index 0000000..fcd207e
Binary files /dev/null and b/public/gb-sct.png differ
diff --git a/public/gb-sct.webp b/public/gb-sct.webp
deleted file mode 100644
index 1045c1c..0000000
Binary files a/public/gb-sct.webp and /dev/null differ
diff --git a/public/gb-wls.png b/public/gb-wls.png
new file mode 100644
index 0000000..1cefa27
Binary files /dev/null and b/public/gb-wls.png differ
diff --git a/public/gb-wls.webp b/public/gb-wls.webp
deleted file mode 100644
index 5209e98..0000000
Binary files a/public/gb-wls.webp and /dev/null differ
diff --git a/public/gb.png b/public/gb.png
new file mode 100644
index 0000000..11dbfb1
Binary files /dev/null and b/public/gb.png differ
diff --git a/public/gb.webp b/public/gb.webp
deleted file mode 100644
index 1c60f98..0000000
Binary files a/public/gb.webp and /dev/null differ
diff --git a/public/gd.png b/public/gd.png
new file mode 100644
index 0000000..5f78187
Binary files /dev/null and b/public/gd.png differ
diff --git a/public/gd.webp b/public/gd.webp
deleted file mode 100644
index 7cb11f7..0000000
Binary files a/public/gd.webp and /dev/null differ
diff --git a/public/ge.png b/public/ge.png
new file mode 100644
index 0000000..fa44ad8
Binary files /dev/null and b/public/ge.png differ
diff --git a/public/ge.webp b/public/ge.webp
deleted file mode 100644
index 21748f1..0000000
Binary files a/public/ge.webp and /dev/null differ
diff --git a/public/gf.png b/public/gf.png
new file mode 100644
index 0000000..b915ef4
Binary files /dev/null and b/public/gf.png differ
diff --git a/public/gf.webp b/public/gf.webp
deleted file mode 100644
index 5b93b7e..0000000
Binary files a/public/gf.webp and /dev/null differ
diff --git a/public/gg.png b/public/gg.png
new file mode 100644
index 0000000..191415d
Binary files /dev/null and b/public/gg.png differ
diff --git a/public/gg.webp b/public/gg.webp
deleted file mode 100644
index 4a8105a..0000000
Binary files a/public/gg.webp and /dev/null differ
diff --git a/public/gh.png b/public/gh.png
new file mode 100644
index 0000000..0141e14
Binary files /dev/null and b/public/gh.png differ
diff --git a/public/gh.webp b/public/gh.webp
deleted file mode 100644
index f632630..0000000
Binary files a/public/gh.webp and /dev/null differ
diff --git a/public/gi.png b/public/gi.png
new file mode 100644
index 0000000..32266c1
Binary files /dev/null and b/public/gi.png differ
diff --git a/public/gi.webp b/public/gi.webp
deleted file mode 100644
index c30fe8e..0000000
Binary files a/public/gi.webp and /dev/null differ
diff --git a/public/gl.png b/public/gl.png
new file mode 100644
index 0000000..5c99f7c
Binary files /dev/null and b/public/gl.png differ
diff --git a/public/gl.webp b/public/gl.webp
deleted file mode 100644
index 89b716f..0000000
Binary files a/public/gl.webp and /dev/null differ
diff --git a/public/gm.png b/public/gm.png
new file mode 100644
index 0000000..b443036
Binary files /dev/null and b/public/gm.png differ
diff --git a/public/gm.webp b/public/gm.webp
deleted file mode 100644
index cb78343..0000000
Binary files a/public/gm.webp and /dev/null differ
diff --git a/public/gn.png b/public/gn.png
new file mode 100644
index 0000000..fcf430a
Binary files /dev/null and b/public/gn.png differ
diff --git a/public/gn.webp b/public/gn.webp
deleted file mode 100644
index f7415dd..0000000
Binary files a/public/gn.webp and /dev/null differ
diff --git a/public/gp.png b/public/gp.png
new file mode 100644
index 0000000..14c8a04
Binary files /dev/null and b/public/gp.png differ
diff --git a/public/gp.webp b/public/gp.webp
deleted file mode 100644
index 77f2662..0000000
Binary files a/public/gp.webp and /dev/null differ
diff --git a/public/gq.png b/public/gq.png
new file mode 100644
index 0000000..7b49db6
Binary files /dev/null and b/public/gq.png differ
diff --git a/public/gq.webp b/public/gq.webp
deleted file mode 100644
index c05284c..0000000
Binary files a/public/gq.webp and /dev/null differ
diff --git a/public/gr.png b/public/gr.png
new file mode 100644
index 0000000..8f38d1c
Binary files /dev/null and b/public/gr.png differ
diff --git a/public/gr.webp b/public/gr.webp
deleted file mode 100644
index cc96cce..0000000
Binary files a/public/gr.webp and /dev/null differ
diff --git a/public/gs.png b/public/gs.png
new file mode 100644
index 0000000..8f522ac
Binary files /dev/null and b/public/gs.png differ
diff --git a/public/gs.webp b/public/gs.webp
deleted file mode 100644
index ddf73e7..0000000
Binary files a/public/gs.webp and /dev/null differ
diff --git a/public/gt.png b/public/gt.png
new file mode 100644
index 0000000..207353d
Binary files /dev/null and b/public/gt.png differ
diff --git a/public/gt.webp b/public/gt.webp
deleted file mode 100644
index dc64e4b..0000000
Binary files a/public/gt.webp and /dev/null differ
diff --git a/public/gu.png b/public/gu.png
new file mode 100644
index 0000000..2d4fb12
Binary files /dev/null and b/public/gu.png differ
diff --git a/public/gu.webp b/public/gu.webp
deleted file mode 100644
index 9d9b42d..0000000
Binary files a/public/gu.webp and /dev/null differ
diff --git a/public/gw.png b/public/gw.png
new file mode 100644
index 0000000..65ce4c1
Binary files /dev/null and b/public/gw.png differ
diff --git a/public/gw.webp b/public/gw.webp
deleted file mode 100644
index 38ceeff..0000000
Binary files a/public/gw.webp and /dev/null differ
diff --git a/public/gy.png b/public/gy.png
new file mode 100644
index 0000000..d920baa
Binary files /dev/null and b/public/gy.png differ
diff --git a/public/gy.webp b/public/gy.webp
deleted file mode 100644
index fd18fda..0000000
Binary files a/public/gy.webp and /dev/null differ
diff --git a/public/hk.png b/public/hk.png
new file mode 100644
index 0000000..3169839
Binary files /dev/null and b/public/hk.png differ
diff --git a/public/hk.webp b/public/hk.webp
deleted file mode 100644
index 0c9abd4..0000000
Binary files a/public/hk.webp and /dev/null differ
diff --git a/public/hm.png b/public/hm.png
new file mode 100644
index 0000000..4b69254
Binary files /dev/null and b/public/hm.png differ
diff --git a/public/hm.webp b/public/hm.webp
deleted file mode 100644
index 5506262..0000000
Binary files a/public/hm.webp and /dev/null differ
diff --git a/public/hn.png b/public/hn.png
new file mode 100644
index 0000000..34f552d
Binary files /dev/null and b/public/hn.png differ
diff --git a/public/hn.webp b/public/hn.webp
deleted file mode 100644
index da58c34..0000000
Binary files a/public/hn.webp and /dev/null differ
diff --git a/public/hr.png b/public/hr.png
new file mode 100644
index 0000000..9e54b17
Binary files /dev/null and b/public/hr.png differ
diff --git a/public/hr.webp b/public/hr.webp
deleted file mode 100644
index bb8ac28..0000000
Binary files a/public/hr.webp and /dev/null differ
diff --git a/public/ht.png b/public/ht.png
new file mode 100644
index 0000000..1d166e6
Binary files /dev/null and b/public/ht.png differ
diff --git a/public/ht.webp b/public/ht.webp
deleted file mode 100644
index 29a5363..0000000
Binary files a/public/ht.webp and /dev/null differ
diff --git a/public/hu.png b/public/hu.png
new file mode 100644
index 0000000..b8f72fd
Binary files /dev/null and b/public/hu.png differ
diff --git a/public/hu.webp b/public/hu.webp
deleted file mode 100644
index 1a76ca1..0000000
Binary files a/public/hu.webp and /dev/null differ
diff --git a/public/id.png b/public/id.png
new file mode 100644
index 0000000..8e23eaf
Binary files /dev/null and b/public/id.png differ
diff --git a/public/id.webp b/public/id.webp
deleted file mode 100644
index a40c4fb..0000000
Binary files a/public/id.webp and /dev/null differ
diff --git a/public/ie.png b/public/ie.png
new file mode 100644
index 0000000..b5bc982
Binary files /dev/null and b/public/ie.png differ
diff --git a/public/ie.webp b/public/ie.webp
deleted file mode 100644
index 6f921a0..0000000
Binary files a/public/ie.webp and /dev/null differ
diff --git a/public/il.png b/public/il.png
new file mode 100644
index 0000000..dd16445
Binary files /dev/null and b/public/il.png differ
diff --git a/public/il.webp b/public/il.webp
deleted file mode 100644
index 0ed8647..0000000
Binary files a/public/il.webp and /dev/null differ
diff --git a/public/im.png b/public/im.png
new file mode 100644
index 0000000..6962325
Binary files /dev/null and b/public/im.png differ
diff --git a/public/im.webp b/public/im.webp
deleted file mode 100644
index 3a57323..0000000
Binary files a/public/im.webp and /dev/null differ
diff --git a/public/in.png b/public/in.png
new file mode 100644
index 0000000..b66497b
Binary files /dev/null and b/public/in.png differ
diff --git a/public/in.webp b/public/in.webp
deleted file mode 100644
index 94f3f52..0000000
Binary files a/public/in.webp and /dev/null differ
diff --git a/public/io.png b/public/io.png
new file mode 100644
index 0000000..0699aab
Binary files /dev/null and b/public/io.png differ
diff --git a/public/io.webp b/public/io.webp
deleted file mode 100644
index 4bc6d52..0000000
Binary files a/public/io.webp and /dev/null differ
diff --git a/public/iq.png b/public/iq.png
new file mode 100644
index 0000000..c8bcfd8
Binary files /dev/null and b/public/iq.png differ
diff --git a/public/iq.webp b/public/iq.webp
deleted file mode 100644
index d567b06..0000000
Binary files a/public/iq.webp and /dev/null differ
diff --git a/public/ir.png b/public/ir.png
new file mode 100644
index 0000000..c553c49
Binary files /dev/null and b/public/ir.png differ
diff --git a/public/ir.webp b/public/ir.webp
deleted file mode 100644
index 2437fee..0000000
Binary files a/public/ir.webp and /dev/null differ
diff --git a/public/is.png b/public/is.png
new file mode 100644
index 0000000..ef873a4
Binary files /dev/null and b/public/is.png differ
diff --git a/public/is.webp b/public/is.webp
deleted file mode 100644
index 761a332..0000000
Binary files a/public/is.webp and /dev/null differ
diff --git a/public/it.png b/public/it.png
new file mode 100644
index 0000000..6123631
Binary files /dev/null and b/public/it.png differ
diff --git a/public/it.webp b/public/it.webp
deleted file mode 100644
index e994c11..0000000
Binary files a/public/it.webp and /dev/null differ
diff --git a/public/je.png b/public/je.png
new file mode 100644
index 0000000..202282f
Binary files /dev/null and b/public/je.png differ
diff --git a/public/je.webp b/public/je.webp
deleted file mode 100644
index 189cf08..0000000
Binary files a/public/je.webp and /dev/null differ
diff --git a/public/jm.png b/public/jm.png
new file mode 100644
index 0000000..dc17929
Binary files /dev/null and b/public/jm.png differ
diff --git a/public/jm.webp b/public/jm.webp
deleted file mode 100644
index 6520405..0000000
Binary files a/public/jm.webp and /dev/null differ
diff --git a/public/jo.png b/public/jo.png
new file mode 100644
index 0000000..dde94fd
Binary files /dev/null and b/public/jo.png differ
diff --git a/public/jo.webp b/public/jo.webp
deleted file mode 100644
index 42be075..0000000
Binary files a/public/jo.webp and /dev/null differ
diff --git a/public/jp.png b/public/jp.png
new file mode 100644
index 0000000..2b89afe
Binary files /dev/null and b/public/jp.png differ
diff --git a/public/jp.webp b/public/jp.webp
deleted file mode 100644
index fcda6f6..0000000
Binary files a/public/jp.webp and /dev/null differ
diff --git a/public/ke.png b/public/ke.png
new file mode 100644
index 0000000..5c2a6ab
Binary files /dev/null and b/public/ke.png differ
diff --git a/public/ke.webp b/public/ke.webp
deleted file mode 100644
index 36cfde4..0000000
Binary files a/public/ke.webp and /dev/null differ
diff --git a/public/kg.png b/public/kg.png
new file mode 100644
index 0000000..47e28be
Binary files /dev/null and b/public/kg.png differ
diff --git a/public/kg.webp b/public/kg.webp
deleted file mode 100644
index 56ab566..0000000
Binary files a/public/kg.webp and /dev/null differ
diff --git a/public/kh.png b/public/kh.png
new file mode 100644
index 0000000..d7164bd
Binary files /dev/null and b/public/kh.png differ
diff --git a/public/kh.webp b/public/kh.webp
deleted file mode 100644
index 679f091..0000000
Binary files a/public/kh.webp and /dev/null differ
diff --git a/public/ki.png b/public/ki.png
new file mode 100644
index 0000000..5cf32cd
Binary files /dev/null and b/public/ki.png differ
diff --git a/public/ki.webp b/public/ki.webp
deleted file mode 100644
index d9bf58b..0000000
Binary files a/public/ki.webp and /dev/null differ
diff --git a/public/km.png b/public/km.png
new file mode 100644
index 0000000..ff73a85
Binary files /dev/null and b/public/km.png differ
diff --git a/public/km.webp b/public/km.webp
deleted file mode 100644
index 9e65931..0000000
Binary files a/public/km.webp and /dev/null differ
diff --git a/public/kn.png b/public/kn.png
new file mode 100644
index 0000000..a0bd5f8
Binary files /dev/null and b/public/kn.png differ
diff --git a/public/kn.webp b/public/kn.webp
deleted file mode 100644
index 7c7a86e..0000000
Binary files a/public/kn.webp and /dev/null differ
diff --git a/public/kp.png b/public/kp.png
new file mode 100644
index 0000000..f014645
Binary files /dev/null and b/public/kp.png differ
diff --git a/public/kp.webp b/public/kp.webp
deleted file mode 100644
index 6f55d0d..0000000
Binary files a/public/kp.webp and /dev/null differ
diff --git a/public/kr.png b/public/kr.png
new file mode 100644
index 0000000..0174cd4
Binary files /dev/null and b/public/kr.png differ
diff --git a/public/kr.webp b/public/kr.webp
deleted file mode 100644
index 1e0faf6..0000000
Binary files a/public/kr.webp and /dev/null differ
diff --git a/public/kw.png b/public/kw.png
new file mode 100644
index 0000000..89205c2
Binary files /dev/null and b/public/kw.png differ
diff --git a/public/kw.webp b/public/kw.webp
deleted file mode 100644
index 2ab51f5..0000000
Binary files a/public/kw.webp and /dev/null differ
diff --git a/public/ky.png b/public/ky.png
new file mode 100644
index 0000000..34700ac
Binary files /dev/null and b/public/ky.png differ
diff --git a/public/ky.webp b/public/ky.webp
deleted file mode 100644
index 19675aa..0000000
Binary files a/public/ky.webp and /dev/null differ
diff --git a/public/kz.png b/public/kz.png
new file mode 100644
index 0000000..ccfc673
Binary files /dev/null and b/public/kz.png differ
diff --git a/public/kz.webp b/public/kz.webp
deleted file mode 100644
index 490dc6c..0000000
Binary files a/public/kz.webp and /dev/null differ
diff --git a/public/la.png b/public/la.png
new file mode 100644
index 0000000..da8e25e
Binary files /dev/null and b/public/la.png differ
diff --git a/public/la.webp b/public/la.webp
deleted file mode 100644
index ba91834..0000000
Binary files a/public/la.webp and /dev/null differ
diff --git a/public/lb.png b/public/lb.png
new file mode 100644
index 0000000..f123d98
Binary files /dev/null and b/public/lb.png differ
diff --git a/public/lb.webp b/public/lb.webp
deleted file mode 100644
index 4695d75..0000000
Binary files a/public/lb.webp and /dev/null differ
diff --git a/public/lc.png b/public/lc.png
new file mode 100644
index 0000000..7240d04
Binary files /dev/null and b/public/lc.png differ
diff --git a/public/lc.webp b/public/lc.webp
deleted file mode 100644
index 3ca5bf5..0000000
Binary files a/public/lc.webp and /dev/null differ
diff --git a/public/li.png b/public/li.png
new file mode 100644
index 0000000..07dfb83
Binary files /dev/null and b/public/li.png differ
diff --git a/public/li.webp b/public/li.webp
deleted file mode 100644
index 4e0ea20..0000000
Binary files a/public/li.webp and /dev/null differ
diff --git a/public/lk.png b/public/lk.png
new file mode 100644
index 0000000..b0e2526
Binary files /dev/null and b/public/lk.png differ
diff --git a/public/lk.webp b/public/lk.webp
deleted file mode 100644
index 510ebaa..0000000
Binary files a/public/lk.webp and /dev/null differ
diff --git a/public/lr.png b/public/lr.png
new file mode 100644
index 0000000..6d3074d
Binary files /dev/null and b/public/lr.png differ
diff --git a/public/lr.webp b/public/lr.webp
deleted file mode 100644
index f7c0c8a..0000000
Binary files a/public/lr.webp and /dev/null differ
diff --git a/public/ls.png b/public/ls.png
new file mode 100644
index 0000000..08e879f
Binary files /dev/null and b/public/ls.png differ
diff --git a/public/ls.webp b/public/ls.webp
deleted file mode 100644
index 8c0a20f..0000000
Binary files a/public/ls.webp and /dev/null differ
diff --git a/public/lt.png b/public/lt.png
new file mode 100644
index 0000000..99def68
Binary files /dev/null and b/public/lt.png differ
diff --git a/public/lt.webp b/public/lt.webp
deleted file mode 100644
index 301b790..0000000
Binary files a/public/lt.webp and /dev/null differ
diff --git a/public/lu.png b/public/lu.png
new file mode 100644
index 0000000..837e834
Binary files /dev/null and b/public/lu.png differ
diff --git a/public/lu.webp b/public/lu.webp
deleted file mode 100644
index ab11fd2..0000000
Binary files a/public/lu.webp and /dev/null differ
diff --git a/public/lv.png b/public/lv.png
new file mode 100644
index 0000000..5e65fa5
Binary files /dev/null and b/public/lv.png differ
diff --git a/public/lv.webp b/public/lv.webp
deleted file mode 100644
index 3424232..0000000
Binary files a/public/lv.webp and /dev/null differ
diff --git a/public/ly.png b/public/ly.png
new file mode 100644
index 0000000..4a60c80
Binary files /dev/null and b/public/ly.png differ
diff --git a/public/ly.webp b/public/ly.webp
deleted file mode 100644
index e1d62aa..0000000
Binary files a/public/ly.webp and /dev/null differ
diff --git a/public/ma.png b/public/ma.png
new file mode 100644
index 0000000..3eea0ba
Binary files /dev/null and b/public/ma.png differ
diff --git a/public/ma.webp b/public/ma.webp
deleted file mode 100644
index db92062..0000000
Binary files a/public/ma.webp and /dev/null differ
diff --git a/public/mc.png b/public/mc.png
new file mode 100644
index 0000000..a0557f9
Binary files /dev/null and b/public/mc.png differ
diff --git a/public/mc.webp b/public/mc.webp
deleted file mode 100644
index 98290ea..0000000
Binary files a/public/mc.webp and /dev/null differ
diff --git a/public/md.png b/public/md.png
new file mode 100644
index 0000000..86cb04a
Binary files /dev/null and b/public/md.png differ
diff --git a/public/md.webp b/public/md.webp
deleted file mode 100644
index ab21db6..0000000
Binary files a/public/md.webp and /dev/null differ
diff --git a/public/me.png b/public/me.png
new file mode 100644
index 0000000..6fa72c4
Binary files /dev/null and b/public/me.png differ
diff --git a/public/me.webp b/public/me.webp
deleted file mode 100644
index b991b37..0000000
Binary files a/public/me.webp and /dev/null differ
diff --git a/public/mf.png b/public/mf.png
new file mode 100644
index 0000000..e258e6a
Binary files /dev/null and b/public/mf.png differ
diff --git a/public/mf.webp b/public/mf.webp
deleted file mode 100644
index bb0eb17..0000000
Binary files a/public/mf.webp and /dev/null differ
diff --git a/public/mg.png b/public/mg.png
new file mode 100644
index 0000000..488cb7f
Binary files /dev/null and b/public/mg.png differ
diff --git a/public/mg.webp b/public/mg.webp
deleted file mode 100644
index 8388d1a..0000000
Binary files a/public/mg.webp and /dev/null differ
diff --git a/public/mh.png b/public/mh.png
new file mode 100644
index 0000000..15fe9f9
Binary files /dev/null and b/public/mh.png differ
diff --git a/public/mh.webp b/public/mh.webp
deleted file mode 100644
index 2f5faf6..0000000
Binary files a/public/mh.webp and /dev/null differ
diff --git a/public/mk.png b/public/mk.png
new file mode 100644
index 0000000..8dc5dc9
Binary files /dev/null and b/public/mk.png differ
diff --git a/public/mk.webp b/public/mk.webp
deleted file mode 100644
index ddb985d..0000000
Binary files a/public/mk.webp and /dev/null differ
diff --git a/public/ml.png b/public/ml.png
new file mode 100644
index 0000000..2cf8433
Binary files /dev/null and b/public/ml.png differ
diff --git a/public/ml.webp b/public/ml.webp
deleted file mode 100644
index 1929d61..0000000
Binary files a/public/ml.webp and /dev/null differ
diff --git a/public/mm.png b/public/mm.png
new file mode 100644
index 0000000..ca35813
Binary files /dev/null and b/public/mm.png differ
diff --git a/public/mm.webp b/public/mm.webp
deleted file mode 100644
index 64e16b0..0000000
Binary files a/public/mm.webp and /dev/null differ
diff --git a/public/mn.png b/public/mn.png
new file mode 100644
index 0000000..16d614c
Binary files /dev/null and b/public/mn.png differ
diff --git a/public/mn.webp b/public/mn.webp
deleted file mode 100644
index 6c06daf..0000000
Binary files a/public/mn.webp and /dev/null differ
diff --git a/public/mo.png b/public/mo.png
new file mode 100644
index 0000000..6cd035b
Binary files /dev/null and b/public/mo.png differ
diff --git a/public/mo.webp b/public/mo.webp
deleted file mode 100644
index 67988fe..0000000
Binary files a/public/mo.webp and /dev/null differ
diff --git a/public/mp.png b/public/mp.png
new file mode 100644
index 0000000..ea999c1
Binary files /dev/null and b/public/mp.png differ
diff --git a/public/mp.webp b/public/mp.webp
deleted file mode 100644
index bbc64ae..0000000
Binary files a/public/mp.webp and /dev/null differ
diff --git a/public/mq.png b/public/mq.png
new file mode 100644
index 0000000..0445a75
Binary files /dev/null and b/public/mq.png differ
diff --git a/public/mq.webp b/public/mq.webp
deleted file mode 100644
index 9be5688..0000000
Binary files a/public/mq.webp and /dev/null differ
diff --git a/public/mr.png b/public/mr.png
new file mode 100644
index 0000000..866483c
Binary files /dev/null and b/public/mr.png differ
diff --git a/public/mr.webp b/public/mr.webp
deleted file mode 100644
index 72b69dd..0000000
Binary files a/public/mr.webp and /dev/null differ
diff --git a/public/ms.png b/public/ms.png
new file mode 100644
index 0000000..297d763
Binary files /dev/null and b/public/ms.png differ
diff --git a/public/ms.webp b/public/ms.webp
deleted file mode 100644
index 830741e..0000000
Binary files a/public/ms.webp and /dev/null differ
diff --git a/public/mt.png b/public/mt.png
new file mode 100644
index 0000000..93797f1
Binary files /dev/null and b/public/mt.png differ
diff --git a/public/mt.webp b/public/mt.webp
deleted file mode 100644
index 6cdf14f..0000000
Binary files a/public/mt.webp and /dev/null differ
diff --git a/public/mu.png b/public/mu.png
new file mode 100644
index 0000000..911e543
Binary files /dev/null and b/public/mu.png differ
diff --git a/public/mu.webp b/public/mu.webp
deleted file mode 100644
index 5d49720..0000000
Binary files a/public/mu.webp and /dev/null differ
diff --git a/public/mv.png b/public/mv.png
new file mode 100644
index 0000000..c153a61
Binary files /dev/null and b/public/mv.png differ
diff --git a/public/mv.webp b/public/mv.webp
deleted file mode 100644
index c6fc74d..0000000
Binary files a/public/mv.webp and /dev/null differ
diff --git a/public/mw.png b/public/mw.png
new file mode 100644
index 0000000..6a84885
Binary files /dev/null and b/public/mw.png differ
diff --git a/public/mw.webp b/public/mw.webp
deleted file mode 100644
index 8fe9ca7..0000000
Binary files a/public/mw.webp and /dev/null differ
diff --git a/public/mx.png b/public/mx.png
new file mode 100644
index 0000000..91fbda2
Binary files /dev/null and b/public/mx.png differ
diff --git a/public/mx.webp b/public/mx.webp
deleted file mode 100644
index fbc65c3..0000000
Binary files a/public/mx.webp and /dev/null differ
diff --git a/public/my.png b/public/my.png
new file mode 100644
index 0000000..10c04ad
Binary files /dev/null and b/public/my.png differ
diff --git a/public/my.webp b/public/my.webp
deleted file mode 100644
index 91e6186..0000000
Binary files a/public/my.webp and /dev/null differ
diff --git a/public/mz.png b/public/mz.png
new file mode 100644
index 0000000..092024a
Binary files /dev/null and b/public/mz.png differ
diff --git a/public/mz.webp b/public/mz.webp
deleted file mode 100644
index ff31094..0000000
Binary files a/public/mz.webp and /dev/null differ
diff --git a/public/na.png b/public/na.png
new file mode 100644
index 0000000..b61dfa8
Binary files /dev/null and b/public/na.png differ
diff --git a/public/na.webp b/public/na.webp
deleted file mode 100644
index 8906c1d..0000000
Binary files a/public/na.webp and /dev/null differ
diff --git a/public/nc.png b/public/nc.png
new file mode 100644
index 0000000..4cc3b99
Binary files /dev/null and b/public/nc.png differ
diff --git a/public/nc.webp b/public/nc.webp
deleted file mode 100644
index 3b3a193..0000000
Binary files a/public/nc.webp and /dev/null differ
diff --git a/public/ne.png b/public/ne.png
new file mode 100644
index 0000000..3890e85
Binary files /dev/null and b/public/ne.png differ
diff --git a/public/ne.webp b/public/ne.webp
deleted file mode 100644
index 1fcbc3c..0000000
Binary files a/public/ne.webp and /dev/null differ
diff --git a/public/nf.png b/public/nf.png
new file mode 100644
index 0000000..95bd616
Binary files /dev/null and b/public/nf.png differ
diff --git a/public/nf.webp b/public/nf.webp
deleted file mode 100644
index 0d54265..0000000
Binary files a/public/nf.webp and /dev/null differ
diff --git a/public/ng.png b/public/ng.png
new file mode 100644
index 0000000..6595522
Binary files /dev/null and b/public/ng.png differ
diff --git a/public/ng.webp b/public/ng.webp
deleted file mode 100644
index 1258e60..0000000
Binary files a/public/ng.webp and /dev/null differ
diff --git a/public/ni.png b/public/ni.png
new file mode 100644
index 0000000..1cbd5b4
Binary files /dev/null and b/public/ni.png differ
diff --git a/public/ni.webp b/public/ni.webp
deleted file mode 100644
index a717ba5..0000000
Binary files a/public/ni.webp and /dev/null differ
diff --git a/public/nl.png b/public/nl.png
new file mode 100644
index 0000000..b77b4bc
Binary files /dev/null and b/public/nl.png differ
diff --git a/public/nl.webp b/public/nl.webp
deleted file mode 100644
index 2a15214..0000000
Binary files a/public/nl.webp and /dev/null differ
diff --git a/public/no.png b/public/no.png
new file mode 100644
index 0000000..ca2ee68
Binary files /dev/null and b/public/no.png differ
diff --git a/public/no.webp b/public/no.webp
deleted file mode 100644
index 6c4c93a..0000000
Binary files a/public/no.webp and /dev/null differ
diff --git a/public/np.png b/public/np.png
new file mode 100644
index 0000000..2dfc019
Binary files /dev/null and b/public/np.png differ
diff --git a/public/np.webp b/public/np.webp
deleted file mode 100644
index bfdff99..0000000
Binary files a/public/np.webp and /dev/null differ
diff --git a/public/nr.png b/public/nr.png
new file mode 100644
index 0000000..8f30a14
Binary files /dev/null and b/public/nr.png differ
diff --git a/public/nr.webp b/public/nr.webp
deleted file mode 100644
index 131a6a6..0000000
Binary files a/public/nr.webp and /dev/null differ
diff --git a/public/nu.png b/public/nu.png
new file mode 100644
index 0000000..e2367ed
Binary files /dev/null and b/public/nu.png differ
diff --git a/public/nu.webp b/public/nu.webp
deleted file mode 100644
index 792b028..0000000
Binary files a/public/nu.webp and /dev/null differ
diff --git a/public/nz.png b/public/nz.png
new file mode 100644
index 0000000..c8cf932
Binary files /dev/null and b/public/nz.png differ
diff --git a/public/nz.webp b/public/nz.webp
deleted file mode 100644
index 960d1ff..0000000
Binary files a/public/nz.webp and /dev/null differ
diff --git a/public/om.png b/public/om.png
new file mode 100644
index 0000000..b1cd606
Binary files /dev/null and b/public/om.png differ
diff --git a/public/om.webp b/public/om.webp
deleted file mode 100644
index 90802bf..0000000
Binary files a/public/om.webp and /dev/null differ
diff --git a/public/pa.png b/public/pa.png
new file mode 100644
index 0000000..a4b9f60
Binary files /dev/null and b/public/pa.png differ
diff --git a/public/pa.webp b/public/pa.webp
deleted file mode 100644
index 4a3492e..0000000
Binary files a/public/pa.webp and /dev/null differ
diff --git a/public/pe.png b/public/pe.png
new file mode 100644
index 0000000..fb4bc51
Binary files /dev/null and b/public/pe.png differ
diff --git a/public/pe.webp b/public/pe.webp
deleted file mode 100644
index c1af45e..0000000
Binary files a/public/pe.webp and /dev/null differ
diff --git a/public/pf.png b/public/pf.png
new file mode 100644
index 0000000..e8f64b1
Binary files /dev/null and b/public/pf.png differ
diff --git a/public/pf.webp b/public/pf.webp
deleted file mode 100644
index 762a591..0000000
Binary files a/public/pf.webp and /dev/null differ
diff --git a/public/pg.png b/public/pg.png
new file mode 100644
index 0000000..d1b1196
Binary files /dev/null and b/public/pg.png differ
diff --git a/public/pg.webp b/public/pg.webp
deleted file mode 100644
index 271935e..0000000
Binary files a/public/pg.webp and /dev/null differ
diff --git a/public/ph.png b/public/ph.png
new file mode 100644
index 0000000..094a067
Binary files /dev/null and b/public/ph.png differ
diff --git a/public/ph.webp b/public/ph.webp
deleted file mode 100644
index 0efc16b..0000000
Binary files a/public/ph.webp and /dev/null differ
diff --git a/public/pk.png b/public/pk.png
new file mode 100644
index 0000000..295d130
Binary files /dev/null and b/public/pk.png differ
diff --git a/public/pk.webp b/public/pk.webp
deleted file mode 100644
index cf43866..0000000
Binary files a/public/pk.webp and /dev/null differ
diff --git a/public/pl.png b/public/pl.png
new file mode 100644
index 0000000..2b2b1d4
Binary files /dev/null and b/public/pl.png differ
diff --git a/public/pl.webp b/public/pl.webp
deleted file mode 100644
index 15fe453..0000000
Binary files a/public/pl.webp and /dev/null differ
diff --git a/public/pm.png b/public/pm.png
new file mode 100644
index 0000000..2c9ad7f
Binary files /dev/null and b/public/pm.png differ
diff --git a/public/pm.webp b/public/pm.webp
deleted file mode 100644
index 36bf894..0000000
Binary files a/public/pm.webp and /dev/null differ
diff --git a/public/pn.png b/public/pn.png
new file mode 100644
index 0000000..3b59c41
Binary files /dev/null and b/public/pn.png differ
diff --git a/public/pn.webp b/public/pn.webp
deleted file mode 100644
index df6850d..0000000
Binary files a/public/pn.webp and /dev/null differ
diff --git a/public/pr.png b/public/pr.png
new file mode 100644
index 0000000..8eedeb3
Binary files /dev/null and b/public/pr.png differ
diff --git a/public/pr.webp b/public/pr.webp
deleted file mode 100644
index 59474e1..0000000
Binary files a/public/pr.webp and /dev/null differ
diff --git a/public/ps.png b/public/ps.png
new file mode 100644
index 0000000..515252f
Binary files /dev/null and b/public/ps.png differ
diff --git a/public/ps.webp b/public/ps.webp
deleted file mode 100644
index e26d912..0000000
Binary files a/public/ps.webp and /dev/null differ
diff --git a/public/pt.png b/public/pt.png
new file mode 100644
index 0000000..e554e60
Binary files /dev/null and b/public/pt.png differ
diff --git a/public/pt.webp b/public/pt.webp
deleted file mode 100644
index e589091..0000000
Binary files a/public/pt.webp and /dev/null differ
diff --git a/public/pw.png b/public/pw.png
new file mode 100644
index 0000000..5449759
Binary files /dev/null and b/public/pw.png differ
diff --git a/public/pw.webp b/public/pw.webp
deleted file mode 100644
index 3482d86..0000000
Binary files a/public/pw.webp and /dev/null differ
diff --git a/public/py.png b/public/py.png
new file mode 100644
index 0000000..3284a8f
Binary files /dev/null and b/public/py.png differ
diff --git a/public/py.webp b/public/py.webp
deleted file mode 100644
index 0a6455a..0000000
Binary files a/public/py.webp and /dev/null differ
diff --git a/public/qa.png b/public/qa.png
new file mode 100644
index 0000000..3bf096c
Binary files /dev/null and b/public/qa.png differ
diff --git a/public/qa.webp b/public/qa.webp
deleted file mode 100644
index 05d4df2..0000000
Binary files a/public/qa.webp and /dev/null differ
diff --git a/public/re.png b/public/re.png
new file mode 100644
index 0000000..795fd58
Binary files /dev/null and b/public/re.png differ
diff --git a/public/re.webp b/public/re.webp
deleted file mode 100644
index be84860..0000000
Binary files a/public/re.webp and /dev/null differ
diff --git a/public/ro.png b/public/ro.png
new file mode 100644
index 0000000..7576102
Binary files /dev/null and b/public/ro.png differ
diff --git a/public/ro.webp b/public/ro.webp
deleted file mode 100644
index 7e9d890..0000000
Binary files a/public/ro.webp and /dev/null differ
diff --git a/public/rs.png b/public/rs.png
new file mode 100644
index 0000000..0660329
Binary files /dev/null and b/public/rs.png differ
diff --git a/public/rs.webp b/public/rs.webp
deleted file mode 100644
index de7fb11..0000000
Binary files a/public/rs.webp and /dev/null differ
diff --git a/public/ru.png b/public/ru.png
new file mode 100644
index 0000000..f9fccf1
Binary files /dev/null and b/public/ru.png differ
diff --git a/public/ru.webp b/public/ru.webp
deleted file mode 100644
index ba6e166..0000000
Binary files a/public/ru.webp and /dev/null differ
diff --git a/public/rw.png b/public/rw.png
new file mode 100644
index 0000000..3ea1985
Binary files /dev/null and b/public/rw.png differ
diff --git a/public/rw.webp b/public/rw.webp
deleted file mode 100644
index cb8eb18..0000000
Binary files a/public/rw.webp and /dev/null differ
diff --git a/public/sa.png b/public/sa.png
new file mode 100644
index 0000000..c14e82d
Binary files /dev/null and b/public/sa.png differ
diff --git a/public/sa.webp b/public/sa.webp
deleted file mode 100644
index e08d60f..0000000
Binary files a/public/sa.webp and /dev/null differ
diff --git a/public/sb.png b/public/sb.png
new file mode 100644
index 0000000..7f34d6a
Binary files /dev/null and b/public/sb.png differ
diff --git a/public/sb.webp b/public/sb.webp
deleted file mode 100644
index c35ab6b..0000000
Binary files a/public/sb.webp and /dev/null differ
diff --git a/public/sc.png b/public/sc.png
new file mode 100644
index 0000000..c0b13b7
Binary files /dev/null and b/public/sc.png differ
diff --git a/public/sc.webp b/public/sc.webp
deleted file mode 100644
index 14a3cdf..0000000
Binary files a/public/sc.webp and /dev/null differ
diff --git a/public/sd.png b/public/sd.png
new file mode 100644
index 0000000..8c54935
Binary files /dev/null and b/public/sd.png differ
diff --git a/public/sd.webp b/public/sd.webp
deleted file mode 100644
index adbe81c..0000000
Binary files a/public/sd.webp and /dev/null differ
diff --git a/public/se.png b/public/se.png
new file mode 100644
index 0000000..acb2940
Binary files /dev/null and b/public/se.png differ
diff --git a/public/se.webp b/public/se.webp
deleted file mode 100644
index b44d95c..0000000
Binary files a/public/se.webp and /dev/null differ
diff --git a/public/sg.png b/public/sg.png
new file mode 100644
index 0000000..45a6e0e
Binary files /dev/null and b/public/sg.png differ
diff --git a/public/sg.webp b/public/sg.webp
deleted file mode 100644
index b7bae95..0000000
Binary files a/public/sg.webp and /dev/null differ
diff --git a/public/sh.png b/public/sh.png
new file mode 100644
index 0000000..c0d6807
Binary files /dev/null and b/public/sh.png differ
diff --git a/public/sh.webp b/public/sh.webp
deleted file mode 100644
index 62b7e11..0000000
Binary files a/public/sh.webp and /dev/null differ
diff --git a/public/si.png b/public/si.png
new file mode 100644
index 0000000..2a51a35
Binary files /dev/null and b/public/si.png differ
diff --git a/public/si.webp b/public/si.webp
deleted file mode 100644
index 5015785..0000000
Binary files a/public/si.webp and /dev/null differ
diff --git a/public/sj.png b/public/sj.png
new file mode 100644
index 0000000..ca2ee68
Binary files /dev/null and b/public/sj.png differ
diff --git a/public/sj.webp b/public/sj.webp
deleted file mode 100644
index 6c4c93a..0000000
Binary files a/public/sj.webp and /dev/null differ
diff --git a/public/sk.png b/public/sk.png
new file mode 100644
index 0000000..7fe47fb
Binary files /dev/null and b/public/sk.png differ
diff --git a/public/sk.webp b/public/sk.webp
deleted file mode 100644
index eac8f3f..0000000
Binary files a/public/sk.webp and /dev/null differ
diff --git a/public/sl.png b/public/sl.png
new file mode 100644
index 0000000..478971f
Binary files /dev/null and b/public/sl.png differ
diff --git a/public/sl.webp b/public/sl.webp
deleted file mode 100644
index 1c3594b..0000000
Binary files a/public/sl.webp and /dev/null differ
diff --git a/public/sm.png b/public/sm.png
new file mode 100644
index 0000000..048e672
Binary files /dev/null and b/public/sm.png differ
diff --git a/public/sm.webp b/public/sm.webp
deleted file mode 100644
index 4882b67..0000000
Binary files a/public/sm.webp and /dev/null differ
diff --git a/public/sn.png b/public/sn.png
new file mode 100644
index 0000000..bbae20e
Binary files /dev/null and b/public/sn.png differ
diff --git a/public/sn.webp b/public/sn.webp
deleted file mode 100644
index 4834266..0000000
Binary files a/public/sn.webp and /dev/null differ
diff --git a/public/so.png b/public/so.png
new file mode 100644
index 0000000..fe34a58
Binary files /dev/null and b/public/so.png differ
diff --git a/public/so.webp b/public/so.webp
deleted file mode 100644
index de479ae..0000000
Binary files a/public/so.webp and /dev/null differ
diff --git a/public/sr.png b/public/sr.png
new file mode 100644
index 0000000..cef0776
Binary files /dev/null and b/public/sr.png differ
diff --git a/public/sr.webp b/public/sr.webp
deleted file mode 100644
index e96a974..0000000
Binary files a/public/sr.webp and /dev/null differ
diff --git a/public/ss.png b/public/ss.png
new file mode 100644
index 0000000..0173039
Binary files /dev/null and b/public/ss.png differ
diff --git a/public/ss.webp b/public/ss.webp
deleted file mode 100644
index 6bf694b..0000000
Binary files a/public/ss.webp and /dev/null differ
diff --git a/public/st.png b/public/st.png
new file mode 100644
index 0000000..2c5a978
Binary files /dev/null and b/public/st.png differ
diff --git a/public/st.webp b/public/st.webp
deleted file mode 100644
index d78ead5..0000000
Binary files a/public/st.webp and /dev/null differ
diff --git a/public/sv.png b/public/sv.png
new file mode 100644
index 0000000..882b9b5
Binary files /dev/null and b/public/sv.png differ
diff --git a/public/sv.webp b/public/sv.webp
deleted file mode 100644
index 4a5fa12..0000000
Binary files a/public/sv.webp and /dev/null differ
diff --git a/public/sx.png b/public/sx.png
new file mode 100644
index 0000000..aacfd05
Binary files /dev/null and b/public/sx.png differ
diff --git a/public/sx.webp b/public/sx.webp
deleted file mode 100644
index d13e4eb..0000000
Binary files a/public/sx.webp and /dev/null differ
diff --git a/public/sy.png b/public/sy.png
new file mode 100644
index 0000000..0bbfc53
Binary files /dev/null and b/public/sy.png differ
diff --git a/public/sy.webp b/public/sy.webp
deleted file mode 100644
index 070334b..0000000
Binary files a/public/sy.webp and /dev/null differ
diff --git a/public/sz.png b/public/sz.png
new file mode 100644
index 0000000..d948ae7
Binary files /dev/null and b/public/sz.png differ
diff --git a/public/sz.webp b/public/sz.webp
deleted file mode 100644
index 8da2034..0000000
Binary files a/public/sz.webp and /dev/null differ
diff --git a/public/tc.png b/public/tc.png
new file mode 100644
index 0000000..170ff34
Binary files /dev/null and b/public/tc.png differ
diff --git a/public/tc.webp b/public/tc.webp
deleted file mode 100644
index aaf1fba..0000000
Binary files a/public/tc.webp and /dev/null differ
diff --git a/public/td.png b/public/td.png
new file mode 100644
index 0000000..acda0b5
Binary files /dev/null and b/public/td.png differ
diff --git a/public/td.webp b/public/td.webp
deleted file mode 100644
index a6e6daf..0000000
Binary files a/public/td.webp and /dev/null differ
diff --git a/public/tf.png b/public/tf.png
new file mode 100644
index 0000000..84fd0b5
Binary files /dev/null and b/public/tf.png differ
diff --git a/public/tf.webp b/public/tf.webp
deleted file mode 100644
index b282f03..0000000
Binary files a/public/tf.webp and /dev/null differ
diff --git a/public/tg.png b/public/tg.png
new file mode 100644
index 0000000..f9d4df9
Binary files /dev/null and b/public/tg.png differ
diff --git a/public/tg.webp b/public/tg.webp
deleted file mode 100644
index 1601ef1..0000000
Binary files a/public/tg.webp and /dev/null differ
diff --git a/public/th.png b/public/th.png
new file mode 100644
index 0000000..d258456
Binary files /dev/null and b/public/th.png differ
diff --git a/public/th.webp b/public/th.webp
deleted file mode 100644
index 0e0b3fb..0000000
Binary files a/public/th.webp and /dev/null differ
diff --git a/public/tj.png b/public/tj.png
new file mode 100644
index 0000000..45270c6
Binary files /dev/null and b/public/tj.png differ
diff --git a/public/tj.webp b/public/tj.webp
deleted file mode 100644
index c89eda3..0000000
Binary files a/public/tj.webp and /dev/null differ
diff --git a/public/tk.png b/public/tk.png
new file mode 100644
index 0000000..0bdbb26
Binary files /dev/null and b/public/tk.png differ
diff --git a/public/tk.webp b/public/tk.webp
deleted file mode 100644
index c865b29..0000000
Binary files a/public/tk.webp and /dev/null differ
diff --git a/public/tl.png b/public/tl.png
new file mode 100644
index 0000000..531745a
Binary files /dev/null and b/public/tl.png differ
diff --git a/public/tl.webp b/public/tl.webp
deleted file mode 100644
index b9436c7..0000000
Binary files a/public/tl.webp and /dev/null differ
diff --git a/public/tm.png b/public/tm.png
new file mode 100644
index 0000000..349e475
Binary files /dev/null and b/public/tm.png differ
diff --git a/public/tm.webp b/public/tm.webp
deleted file mode 100644
index 4447626..0000000
Binary files a/public/tm.webp and /dev/null differ
diff --git a/public/tn.png b/public/tn.png
new file mode 100644
index 0000000..4f1ea12
Binary files /dev/null and b/public/tn.png differ
diff --git a/public/tn.webp b/public/tn.webp
deleted file mode 100644
index 2a06213..0000000
Binary files a/public/tn.webp and /dev/null differ
diff --git a/public/to.png b/public/to.png
new file mode 100644
index 0000000..2db46e2
Binary files /dev/null and b/public/to.png differ
diff --git a/public/to.webp b/public/to.webp
deleted file mode 100644
index 7b70ea9..0000000
Binary files a/public/to.webp and /dev/null differ
diff --git a/public/tr.png b/public/tr.png
new file mode 100644
index 0000000..354e004
Binary files /dev/null and b/public/tr.png differ
diff --git a/public/tr.webp b/public/tr.webp
deleted file mode 100644
index 7c54384..0000000
Binary files a/public/tr.webp and /dev/null differ
diff --git a/public/tt.png b/public/tt.png
new file mode 100644
index 0000000..5d0c471
Binary files /dev/null and b/public/tt.png differ
diff --git a/public/tt.webp b/public/tt.webp
deleted file mode 100644
index b1e5ada..0000000
Binary files a/public/tt.webp and /dev/null differ
diff --git a/public/tv.png b/public/tv.png
new file mode 100644
index 0000000..6c39cfc
Binary files /dev/null and b/public/tv.png differ
diff --git a/public/tv.webp b/public/tv.webp
deleted file mode 100644
index fd4f73d..0000000
Binary files a/public/tv.webp and /dev/null differ
diff --git a/public/tw.png b/public/tw.png
new file mode 100644
index 0000000..6edb9f5
Binary files /dev/null and b/public/tw.png differ
diff --git a/public/tw.webp b/public/tw.webp
deleted file mode 100644
index 9769214..0000000
Binary files a/public/tw.webp and /dev/null differ
diff --git a/public/tz.png b/public/tz.png
new file mode 100644
index 0000000..5fd6b11
Binary files /dev/null and b/public/tz.png differ
diff --git a/public/tz.webp b/public/tz.webp
deleted file mode 100644
index 97f0d6c..0000000
Binary files a/public/tz.webp and /dev/null differ
diff --git a/public/ua.png b/public/ua.png
new file mode 100644
index 0000000..2a7be19
Binary files /dev/null and b/public/ua.png differ
diff --git a/public/ua.webp b/public/ua.webp
deleted file mode 100644
index 24ff5ce..0000000
Binary files a/public/ua.webp and /dev/null differ
diff --git a/public/ug.png b/public/ug.png
new file mode 100644
index 0000000..c9a03b5
Binary files /dev/null and b/public/ug.png differ
diff --git a/public/ug.webp b/public/ug.webp
deleted file mode 100644
index b8918db..0000000
Binary files a/public/ug.webp and /dev/null differ
diff --git a/public/um.png b/public/um.png
new file mode 100644
index 0000000..53e306c
Binary files /dev/null and b/public/um.png differ
diff --git a/public/um.webp b/public/um.webp
deleted file mode 100644
index 3f56288..0000000
Binary files a/public/um.webp and /dev/null differ
diff --git a/public/unknown.png b/public/unknown.png
new file mode 100644
index 0000000..6fd1413
Binary files /dev/null and b/public/unknown.png differ
diff --git a/public/unknown.webp b/public/unknown.webp
deleted file mode 100644
index 3e9ffd2..0000000
Binary files a/public/unknown.webp and /dev/null differ
diff --git a/public/us.png b/public/us.png
new file mode 100644
index 0000000..53e306c
Binary files /dev/null and b/public/us.png differ
diff --git a/public/us.webp b/public/us.webp
deleted file mode 100644
index 3f56288..0000000
Binary files a/public/us.webp and /dev/null differ
diff --git a/public/uy.png b/public/uy.png
new file mode 100644
index 0000000..47f7b1b
Binary files /dev/null and b/public/uy.png differ
diff --git a/public/uy.webp b/public/uy.webp
deleted file mode 100644
index c3ea17d..0000000
Binary files a/public/uy.webp and /dev/null differ
diff --git a/public/uz.png b/public/uz.png
new file mode 100644
index 0000000..2a88095
Binary files /dev/null and b/public/uz.png differ
diff --git a/public/uz.webp b/public/uz.webp
deleted file mode 100644
index dc9d313..0000000
Binary files a/public/uz.webp and /dev/null differ
diff --git a/public/va.png b/public/va.png
new file mode 100644
index 0000000..c4e3292
Binary files /dev/null and b/public/va.png differ
diff --git a/public/va.webp b/public/va.webp
deleted file mode 100644
index 60b6dc5..0000000
Binary files a/public/va.webp and /dev/null differ
diff --git a/public/vc.png b/public/vc.png
new file mode 100644
index 0000000..b3de1fd
Binary files /dev/null and b/public/vc.png differ
diff --git a/public/vc.webp b/public/vc.webp
deleted file mode 100644
index 7f902c6..0000000
Binary files a/public/vc.webp and /dev/null differ
diff --git a/public/ve.png b/public/ve.png
new file mode 100644
index 0000000..fe68383
Binary files /dev/null and b/public/ve.png differ
diff --git a/public/ve.webp b/public/ve.webp
deleted file mode 100644
index 175f724..0000000
Binary files a/public/ve.webp and /dev/null differ
diff --git a/public/vg.png b/public/vg.png
new file mode 100644
index 0000000..17e9cf4
Binary files /dev/null and b/public/vg.png differ
diff --git a/public/vg.webp b/public/vg.webp
deleted file mode 100644
index 20bb0c5..0000000
Binary files a/public/vg.webp and /dev/null differ
diff --git a/public/vi.png b/public/vi.png
new file mode 100644
index 0000000..e60bd51
Binary files /dev/null and b/public/vi.png differ
diff --git a/public/vi.webp b/public/vi.webp
deleted file mode 100644
index 8f89022..0000000
Binary files a/public/vi.webp and /dev/null differ
diff --git a/public/vn.png b/public/vn.png
new file mode 100644
index 0000000..ddff9b5
Binary files /dev/null and b/public/vn.png differ
diff --git a/public/vn.webp b/public/vn.webp
deleted file mode 100644
index 2aff108..0000000
Binary files a/public/vn.webp and /dev/null differ
diff --git a/public/vu.png b/public/vu.png
new file mode 100644
index 0000000..bdbb901
Binary files /dev/null and b/public/vu.png differ
diff --git a/public/vu.webp b/public/vu.webp
deleted file mode 100644
index 354ded4..0000000
Binary files a/public/vu.webp and /dev/null differ
diff --git a/public/wf.png b/public/wf.png
new file mode 100644
index 0000000..b79beaf
Binary files /dev/null and b/public/wf.png differ
diff --git a/public/wf.webp b/public/wf.webp
deleted file mode 100644
index 084b436..0000000
Binary files a/public/wf.webp and /dev/null differ
diff --git a/public/ws.png b/public/ws.png
new file mode 100644
index 0000000..6fc155f
Binary files /dev/null and b/public/ws.png differ
diff --git a/public/ws.webp b/public/ws.webp
deleted file mode 100644
index 08e876e..0000000
Binary files a/public/ws.webp and /dev/null differ
diff --git a/public/xk.png b/public/xk.png
new file mode 100644
index 0000000..faf6886
Binary files /dev/null and b/public/xk.png differ
diff --git a/public/xk.webp b/public/xk.webp
deleted file mode 100644
index 0eb803a..0000000
Binary files a/public/xk.webp and /dev/null differ
diff --git a/public/ye.png b/public/ye.png
new file mode 100644
index 0000000..049b56b
Binary files /dev/null and b/public/ye.png differ
diff --git a/public/ye.webp b/public/ye.webp
deleted file mode 100644
index fff6224..0000000
Binary files a/public/ye.webp and /dev/null differ
diff --git a/public/yt.png b/public/yt.png
new file mode 100644
index 0000000..346fda0
Binary files /dev/null and b/public/yt.png differ
diff --git a/public/yt.webp b/public/yt.webp
deleted file mode 100644
index c44f939..0000000
Binary files a/public/yt.webp and /dev/null differ
diff --git a/public/za.png b/public/za.png
new file mode 100644
index 0000000..ad7e2df
Binary files /dev/null and b/public/za.png differ
diff --git a/public/za.webp b/public/za.webp
deleted file mode 100644
index b63f11b..0000000
Binary files a/public/za.webp and /dev/null differ
diff --git a/public/zm.png b/public/zm.png
new file mode 100644
index 0000000..f9bfe22
Binary files /dev/null and b/public/zm.png differ
diff --git a/public/zm.webp b/public/zm.webp
deleted file mode 100644
index 073bca2..0000000
Binary files a/public/zm.webp and /dev/null differ
diff --git a/public/zw.png b/public/zw.png
new file mode 100644
index 0000000..1f6cd68
Binary files /dev/null and b/public/zw.png differ
diff --git a/public/zw.webp b/public/zw.webp
deleted file mode 100644
index 86305a4..0000000
Binary files a/public/zw.webp and /dev/null differ
diff --git a/services/dns.ts b/services/dns.ts
new file mode 100644
index 0000000..85015e9
--- /dev/null
+++ b/services/dns.ts
@@ -0,0 +1,20 @@
+export const DnsService = {
+ async resolve(hostname: string): Promise {
+ try {
+ const response = await fetch(
+ `https://cloudflare-dns.com/dns-query?name=${hostname}&type=A`,
+ {
+ headers: { accept: 'application/dns-json' },
+ credentials: 'omit'
+ }
+ );
+
+ if (!response.ok) return null;
+
+ const data = await response.json();
+ return data.Answer?.find((r: any) => r.type === 1)?.data || null;
+ } catch (error) {
+ return null;
+ }
+ }
+};
diff --git a/services/geo.ts b/services/geo.ts
index f9eff3a..2101a42 100644
--- a/services/geo.ts
+++ b/services/geo.ts
@@ -1,57 +1,75 @@
-import type { GeoApiResponse, HostInfo } from '@/utils/types';
+import { StorageService } from '@/utils/storage';
+import { IpUtils } from '@/utils/ip';
import { codes } from '@/utils/codes';
-
-const CACHE = new Map();
+import type { GeoData } from '@/utils/types';
export const GeoService = {
- async resolve(ip: string): Promise {
- if (CACHE.has(ip)) return CACHE.get(ip)!;
+ async getGeoData(ip: string): Promise {
+ if (IpUtils.isLocalOrBogon(ip)) {
+ return this.getLocalData(ip);
+ }
+
+ const cached = await StorageService.getGeoCache(ip);
+ if (cached) return cached;
try {
- const res = await fetch(`https://ip.albert.lol/${ip}`);
- if (!res.ok) throw new Error(`Geo API Error: ${res.status}`);
+ const res = await fetch(`https://ip.albert.lol/${ip}`, {
+ method: 'GET',
+ cache: 'force-cache',
+ credentials: 'omit'
+ });
- const data: GeoApiResponse = await res.json();
- CACHE.set(ip, data);
+ if (!res.ok) throw new Error(`API Error ${res.status}`);
- if (CACHE.size > 100) {
- const firstKey = CACHE.keys().next().value;
- if (firstKey) CACHE.delete(firstKey);
- }
+ const raw = await res.json();
+ const data = this.transform(ip, raw);
+ await StorageService.setGeoCache(ip, data);
return data;
} catch (error) {
- console.error('Geo lookup failed', error);
- return null;
+ console.warn('Geo lookup failed for', ip, error);
+ return {
+ ip,
+ countryCode: null,
+ countryName: 'Unknown',
+ city: null,
+ region: null,
+ org: 'Lookup Failed',
+ asn: null,
+ timezone: null,
+ isLocal: false,
+ isBogon: false
+ };
}
},
- mapToHostInfo(url: string, ip: string, geo: GeoApiResponse | null): HostInfo {
- const urlObj = new URL(url);
-
- const info: HostInfo = {
- url,
- domain: urlObj.hostname,
- loading: false,
- error: null,
- isBrowserResource: false,
- network: {
- ip,
- hostname: geo?.hostname || urlObj.hostname,
- asn: geo?.org?.split(' ')[0] || null,
- org: geo?.org || 'Unknown Organization',
- isLocal: false,
- isBogon: geo?.bogon || false,
- },
- location: {
- countryCode: geo?.country || null,
- countryName: geo?.country ? (codes[geo.country.toLowerCase()] || geo.country) : null,
- city: geo?.city || null,
- region: geo?.region || null,
- timezone: geo?.timezone || null,
- }
+ getLocalData(ip: string): GeoData {
+ return {
+ ip,
+ countryCode: null,
+ countryName: 'Local Network',
+ city: null,
+ region: null,
+ org: 'Private Network',
+ asn: null,
+ timezone: null,
+ isLocal: true,
+ isBogon: false
};
+ },
- return info;
+ transform(ip: string, apiData: any): GeoData {
+ return {
+ ip,
+ countryCode: apiData.country || null,
+ countryName: apiData.country ? (codes[apiData.country.toLowerCase()] || apiData.country) : null,
+ city: apiData.city || null,
+ region: apiData.region || null,
+ org: apiData.org || null,
+ asn: apiData.org?.split(' ')[0] || null,
+ timezone: apiData.timezone || null,
+ isLocal: false,
+ isBogon: apiData.bogon || false
+ };
}
};
diff --git a/services/icon.ts b/services/icon.ts
index 8fc8319..b302c37 100644
--- a/services/icon.ts
+++ b/services/icon.ts
@@ -1,63 +1,79 @@
-import { browser } from 'wxt/browser';
-
-const ICON_CACHE = new Map>();
-
export const IconService = {
- async update(tabId: number, countryCode: string | null, isLocal: boolean) {
- try {
- const code = isLocal ? 'unknown' : (countryCode ? countryCode.toLowerCase() : 'unknown');
+ async updateIcon(tabId: number, countryCode: string | null, isLocal: boolean) {
+ const code = isLocal ? 'unknown' : (countryCode?.toLowerCase() || 'unknown');
+ const fileName = `${code}.png`;
- const imageData = await this.getIconData(code);
- await browser.action.setIcon({ tabId, imageData });
+ let success = await this.setIconSafe(tabId, fileName);
+
+ if (!success && code !== 'unknown') {
+ await this.setIconSafe(tabId, 'unknown.png');
+ }
+
+ try {
+ const title = isLocal ? 'Local Resource' : (countryCode ? `Hosted in ${countryCode.toUpperCase()}` : 'Host Info');
+
+ if (typeof chrome !== 'undefined' && chrome.action && chrome.action.setTitle) {
+ chrome.action.setTitle({ tabId, title }, () => {
+ void chrome.runtime.lastError;
+ });
+ } else {
+ await browser.action.setTitle({ tabId, title });
+ }
} catch (e) {
- console.warn('Failed to update icon', e);
}
},
- async getIconData(code: string): Promise> {
- if (ICON_CACHE.has(code)) return ICON_CACHE.get(code)!;
+ async setIconSafe(tabId: number, fileName: string): Promise {
+ let success = await new Promise((resolve) => {
+ if (typeof chrome !== 'undefined' && chrome.action && chrome.action.setIcon) {
+ chrome.action.setIcon({ tabId, path: fileName }, () => {
+ resolve(!chrome.runtime.lastError);
+ });
+ } else {
+ browser.action.setIcon({ tabId, path: fileName })
+ .then(() => resolve(true))
+ .catch(() => resolve(false));
+ }
+ });
- const path = `/${code}.webp`;
- const url = browser.runtime.getURL(path as any);
+ if (success) return true;
try {
- const resp = await fetch(url);
- if (!resp.ok) throw new Error('Icon not found');
+ const url = browser.runtime.getURL(`/${fileName}` as any);
+ const res = await fetch(url);
- const blob = await resp.blob();
+ if (!res.ok) {
+ return false;
+ }
+
+ const blob = await res.blob();
const bitmap = await createImageBitmap(blob);
- const data = await this.processBitmap(bitmap);
+ const size = Math.max(bitmap.width, bitmap.height);
- ICON_CACHE.set(code, data);
- return data;
- } catch {
- if (code !== 'unknown') return this.getIconData('unknown');
- throw new Error('Failed to load fallback icon');
+ if (typeof OffscreenCanvas !== 'undefined') {
+ const canvas = new OffscreenCanvas(size, size);
+ const ctx = canvas.getContext('2d', { willReadFrequently: true });
+ if (!ctx) return false;
+
+ ctx.clearRect(0, 0, size, size);
+ ctx.drawImage(bitmap, (size - bitmap.width) / 2, (size - bitmap.height) / 2);
+ const imageData = ctx.getImageData(0, 0, size, size);
+
+ return await new Promise((resolve) => {
+ if (typeof chrome !== 'undefined' && chrome.action && chrome.action.setIcon) {
+ chrome.action.setIcon({ tabId, imageData: { [size.toString()]: imageData } }, () => {
+ resolve(!chrome.runtime.lastError);
+ });
+ } else {
+ browser.action.setIcon({ tabId, imageData: { [size.toString()]: imageData } })
+ .then(() => resolve(true))
+ .catch(() => resolve(false));
+ }
+ });
+ }
+ return false;
+ } catch (e) {
+ return false;
}
- },
-
- async processBitmap(bitmap: ImageBitmap): Promise> {
- const canvas = new OffscreenCanvas(128, 128);
- const ctx = canvas.getContext('2d', { willReadFrequently: true })!;
-
- // Center and contain
- const ratio = Math.min(canvas.width / bitmap.width, canvas.height / bitmap.height);
- const offsetX = (canvas.width - bitmap.width * ratio) / 2;
- const offsetY = (canvas.height - bitmap.height * ratio) / 2;
-
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, offsetX, offsetY, bitmap.width * ratio, bitmap.height * ratio);
-
- const sizes = [16, 32, 48, 128];
- const result: Record = {};
-
- for (const size of sizes) {
- const sCanvas = new OffscreenCanvas(size, size);
- const sCtx = sCanvas.getContext('2d')!;
- sCtx.drawImage(canvas, 0, 0, size, size);
- result[size] = sCtx.getImageData(0, 0, size, size);
- }
-
- return result;
}
};
diff --git a/services/tab.ts b/services/tab.ts
deleted file mode 100644
index ca8f9b4..0000000
--- a/services/tab.ts
+++ /dev/null
@@ -1,156 +0,0 @@
-import { IpUtils } from '@/utils/ip';
-import { StorageService } from '@/utils/storage';
-import { GeoService } from './geo';
-import { IconService } from './icon';
-import type { HostInfo } from '@/utils/types';
-
-export const Tab = {
- /**
- * Handle System/Browser specific pages
- */
- async processSystemPage(tabId: number) {
- await IconService.update(tabId, null, true);
- },
-
- /**
- * Handle Network Errors (DNS, Connection Refused, etc)
- */
- async handleError(tabId: number, url: string, error: string) {
- let message = error;
-
- // Normalize error string (remove net:: prefix if present)
- const code = error.startsWith('net::') ? error.replace('net::', '') : error;
-
- switch (code) {
- case 'ERR_NAME_NOT_RESOLVED':
- case 'NS_ERROR_UNKNOWN_HOST':
- message = 'DNS Resolution Failed (NXDOMAIN)';
- break;
- case 'ERR_CONNECTION_REFUSED':
- case 'NS_ERROR_CONNECTION_REFUSED':
- message = 'Connection Refused';
- break;
- case 'ERR_INTERNET_DISCONNECTED':
- case 'NS_ERROR_OFFLINE':
- message = 'No Internet Connection';
- break;
- case 'ERR_CONNECTION_TIMED_OUT':
- case 'NS_ERROR_NET_TIMEOUT':
- message = 'Connection Timed Out';
- break;
- case 'ERR_ADDRESS_UNREACHABLE':
- message = 'Address Unreachable';
- break;
- default:
- // Fallback: clean up the code for display (e.g. ERR_SSL_PROTOCOL_ERROR -> Err ssl protocol error)
- message = code.replace(/_/g, ' ').toLowerCase();
- message = message.charAt(0).toUpperCase() + message.slice(1);
- break;
- }
-
- const errorInfo: HostInfo = {
- url,
- domain: new URL(url).hostname,
- loading: false,
- error: message,
- network: null,
- location: null,
- isBrowserResource: false
- };
-
- await StorageService.set(tabId, errorInfo);
- await IconService.update(tabId, 'unknown', false);
- },
-
- /**
- * Main entry point to process a tab's data
- */
- async process(tabId: number, url: string, ip?: string) {
- // Initial State (Loading)
- const initialState: HostInfo = {
- url,
- domain: new URL(url).hostname,
- loading: true,
- error: null,
- network: null,
- location: null,
- isBrowserResource: false
- };
-
- // Don't overwrite if we already have data for this exact URL,
- // but do update if we have a new IP
- const existing = await StorageService.get(tabId);
- if (!existing || existing.url !== url) {
- await StorageService.set(tabId, initialState);
- }
-
- // Resolve IP if missing
- if (!ip) {
- return;
- }
-
- // Handle Local/Private IPs (Bogons)
- if (IpUtils.isLocalOrBogon(ip)) {
- const localInfo: HostInfo = {
- ...initialState,
- loading: false,
- network: {
- ip,
- hostname: 'Local Network',
- asn: null,
- org: 'Private Network',
- isLocal: true,
- isBogon: false
- },
- location: null
- };
- await StorageService.set(tabId, localInfo);
- await IconService.update(tabId, null, true);
- return;
- }
-
- // Fetch Public Data
- const geoData = await GeoService.resolve(ip);
-
- // If Geo lookup fails (e.g. LAN domain with public IP, or API down),
- // we still want to show the IP we captured.
- if (!geoData) {
- const fallbackInfo: HostInfo = {
- ...initialState,
- loading: false,
- network: {
- ip,
- hostname: null,
- asn: null,
- org: 'Unknown',
- isLocal: false,
- isBogon: false
- },
- location: {
- countryCode: null,
- countryName: 'Unknown Location',
- city: null,
- region: null,
- timezone: null
- }
- };
- await StorageService.set(tabId, fallbackInfo);
- await IconService.update(tabId, 'unknown', false);
- return;
- }
-
- // Save Final State
- const finalInfo = GeoService.mapToHostInfo(url, ip, geoData);
- await StorageService.set(tabId, finalInfo);
-
- // Determine Icon
- const asn = finalInfo.network?.asn;
- let iconCode = finalInfo.location?.countryCode || null;
-
- if (asn === 'AS13335') {
- iconCode = 'cloudflare';
- }
-
- await IconService.update(tabId, iconCode, false);
- }
-};
diff --git a/utils/ip.ts b/utils/ip.ts
index dcca573..ef7afda 100644
--- a/utils/ip.ts
+++ b/utils/ip.ts
@@ -1,32 +1,29 @@
const ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
-const ipv6Regex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,2}(:[0-9a-fA-F]{1,4}){1,5})|([0-9a-fA-F]{1,4}:)((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
+const ipv6Regex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,3}(:[0-9a-fA-F]{1,4}){1,4})|([0-9a-fA-F]{1,2}(:[0-9a-fA-F]{1,4}){1,5})|([0-9a-fA-F]{1,4}:)((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
export const IpUtils = {
isValidIP(ip: string): boolean {
+ if (!ip) return false;
const clean = ip.replace(/^\[|\]$/g, '');
return ipv4Regex.test(clean) || ipv6Regex.test(clean);
},
isLocalOrBogon(ip: string): boolean {
+ if (!ip) return false;
const clean = ip.replace(/^\[|\]$/g, '');
- // IPv6 Local/Bogon
if (clean === '::1' || clean === '::') return true;
if (clean.toLowerCase().startsWith('fe80:')) return true;
if (clean.toLowerCase().startsWith('fc00:')) return true;
- if (clean.toLowerCase().startsWith('fd00:')) return true;
- if (!clean.includes('.')) return false;
-
- // IPv4 Local/Bogon
- const parts = clean.split('.').map(Number);
- if (parts.length !== 4) return false;
-
- if (parts[0] === 10) return true;
- if (parts[0] === 192 && parts[1] === 168) return true;
- if (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) return true;
- if (parts[0] === 127) return true;
- if (parts[0] === 169 && parts[1] === 254) return true;
+ if (clean.includes('.')) {
+ const parts = clean.split('.').map(Number);
+ if (parts[0] === 10) return true;
+ if (parts[0] === 192 && parts[1] === 168) return true;
+ if (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) return true;
+ if (parts[0] === 127) return true;
+ if (parts[0] === 169 && parts[1] === 254) return true;
+ }
return false;
}
diff --git a/utils/storage.ts b/utils/storage.ts
index c514f3e..1fdc6ca 100644
--- a/utils/storage.ts
+++ b/utils/storage.ts
@@ -1,31 +1,57 @@
-import type { HostInfo } from './types';
+const CACHE_TTL = 1000 * 60 * 60 * 24;
export const StorageService = {
- /**
- * Returns the storage key for a specific tab with the required type prefix
- */
- getKey(tabId: number): `session:${string}` {
- return `session:host-info-${tabId}`;
+ async getTabState(tabId: number): Promise {
+ const key = `tab_${tabId}`;
+ if (browser.storage.session) {
+ try {
+ const res = await browser.storage.session.get(key);
+ if (res[key]) return res[key] as TabState;
+ } catch { }
+ }
+ const res = await browser.storage.local.get(`session_${key}`);
+ return (res[`session_${key}`] as TabState) || null;
},
- /**
- * Save host info for a tab
- */
- async set(tabId: number, data: HostInfo) {
- await storage.setItem(this.getKey(tabId), data);
+ async setTabState(tabId: number, state: TabState): Promise {
+ const key = `tab_${tabId}`;
+ if (browser.storage.session) {
+ try {
+ await browser.storage.session.set({ [key]: state });
+ return;
+ } catch { }
+ }
+ await browser.storage.local.set({ [`session_${key}`]: state });
},
- /**
- * Get host info for a tab
- */
- async get(tabId: number): Promise {
- return await storage.getItem(this.getKey(tabId));
+ async removeTabState(tabId: number): Promise {
+ const key = `tab_${tabId}`;
+ if (browser.storage.session) {
+ try {
+ await browser.storage.session.remove(key);
+ return;
+ } catch { }
+ }
+ await browser.storage.local.remove(`session_${key}`);
},
- /**
- * Clear data when a tab is closed
- */
- async remove(tabId: number) {
- await storage.removeItem(this.getKey(tabId));
+ async getGeoCache(ip: string): Promise {
+ const key = `geo_${ip.replace(/:/g, '_')}`;
+ const res = await browser.storage.local.get(key);
+ const entry = res[key] as CacheEntry | undefined;
+
+ if (!entry) return null;
+
+ if (Date.now() - entry.timestamp > CACHE_TTL) {
+ await browser.storage.local.remove(key);
+ return null;
+ }
+ return entry.data;
+ },
+
+ async setGeoCache(ip: string, data: GeoData): Promise {
+ const key = `geo_${ip.replace(/:/g, '_')}`;
+ const entry: CacheEntry = { data, timestamp: Date.now() };
+ await browser.storage.local.set({ [key]: entry });
}
};
diff --git a/utils/types.ts b/utils/types.ts
index 0230f15..a4ee09d 100644
--- a/utils/types.ts
+++ b/utils/types.ts
@@ -1,38 +1,28 @@
-export interface HostLocation {
+export interface GeoData {
+ ip: string;
countryCode: string | null;
countryName: string | null;
city: string | null;
region: string | null;
- timezone: string | null;
-}
-
-export interface HostNetwork {
- ip: string;
- asn: string | null;
org: string | null;
- hostname: string | null;
+ asn: string | null;
+ timezone: string | null;
isLocal: boolean;
isBogon: boolean;
}
-export interface HostInfo {
+export type LoadingStatus = 'idle' | 'loading' | 'success' | 'error';
+
+export interface TabState {
url: string;
domain: string;
- network: HostNetwork | null;
- location: HostLocation | null;
- error: string | null;
- loading: boolean;
- isBrowserResource: boolean;
+ status: LoadingStatus;
+ data: GeoData | null;
+ errorMessage: string | null;
+ lastUpdated: number;
}
-export interface GeoApiResponse {
- ip: string;
- hostname?: string;
- city?: string;
- region?: string;
- country?: string;
- loc?: string;
- org?: string;
- timezone?: string;
- bogon?: boolean;
+export interface CacheEntry {
+ data: GeoData;
+ timestamp: number;
}
diff --git a/wxt.config.ts b/wxt.config.ts
index 87fa7d0..f8edf2b 100644
--- a/wxt.config.ts
+++ b/wxt.config.ts
@@ -10,8 +10,8 @@ export default defineConfig({
version: '2.0.0',
permissions: [
'tabs',
- 'activeTab',
'webRequest',
+ 'webNavigation',
'storage'
],
host_permissions: [