Repository: web-scrobbler/web-scrobbler
Pull request #3892 (2023-06-13 21:49:52)

Fix Idagio connector
**Describe the changes you made**
Fixed the Idagio connector not recognizing when a track is playing.

**Additional context**
The Idagio connector was not scrobbling music. The `isPlaying` check expects the play button label to equal "Pause" when a track is playing which is also what is visible in the DOM, however they use a `text-transform: uppercase` CSS styling on it.
I call `toUpper` on the found text, so it doesn't break again should they remove the styling.

hornbuckle: If the text inside the element is "Pause," CSS text-transform shouldn't have any effect on the connector script since it would only affect how the browser renders the text.
Can you provide a link to show the issue you're trying to fix?
LibertyFrog: > If the text inside the element is "Pause," CSS text-transform shouldn't have any effect on the connector script since it would only affect how the browser renders the text. Can you provide a link to show the issue you're trying to fix?

That is not the behaviour I'm observing. As for a link: go to https://app.idagio.com and click the play icon on any album tile. When I do it the extension doesn't start scrobbling and when I look at the `State` object I see the `isPlaying` property is still `false`.

This is what I see in the DOM for the pause button selector, "Pause":
![pause-in-dom](https://github.com/web-scrobbler/web-scrobbler/assets/124195606/f40ca688-6d8a-4b66-8866-4d623ca68829)

This is the CSS applying the `text-transform`:
![css-class](https://github.com/web-scrobbler/web-scrobbler/assets/124195606/2f1965b2-ed5e-4065-9392-e18aa0d03e0b)

I added logging to the isPlaying getter (without the `toUpper` I added later):
![log-text](https://github.com/web-scrobbler/web-scrobbler/assets/124195606/2a01c068-311e-4803-90d7-49f13bfd3310)

This is the log output, all uppercase "PAUSE":
![log-value](https://github.com/web-scrobbler/web-scrobbler/assets/124195606/e28ac5ae-4220-40e9-96ce-2f5887d76205)

This is the log output after toggling `text-transform` in the browser dev tools (no other change):
![css-no-text-transform](https://github.com/web-scrobbler/web-scrobbler/assets/124195606/ec25457e-1909-4cb9-9a6f-767febcfb458)
![log-value-no-text-transform](https://github.com/web-scrobbler/web-scrobbler/assets/124195606/bd966717-6878-482b-a569-56fe20678995)


Patch:
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 421564a4..58b96b1e 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -91,7 +91,7 @@ jobs:
         run: echo "PACKAGE_VERSION=$(jq .version package.json -r)" >> $GITHUB_ENV
 
       - name: Publish the extension for Edge
-        uses: inverse/edge-addon@v1.0.7
+        uses: inverse/edge-addon@v1.0.8
         with:
           product_id: ${{ secrets.EDGE_PRODUCT_ID }}
           client_id: ${{ secrets.EDGE_CLIENT_ID }}
diff --git a/.nvmrc b/.nvmrc
index 6d80269a..603606bc 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1,1 +1,1 @@
-18.16.0
+18.17.0
diff --git a/package-lock.json b/package-lock.json
index a8713a6b..eccad5bd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,19 +1,19 @@
 {
   "name": "web-scrobbler",
-  "version": "3.0.12",
+  "version": "3.0.15",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "web-scrobbler",
-      "version": "3.0.12",
+      "version": "3.0.15",
       "license": "MIT",
       "dependencies": {
-        "@suid/icons-material": "0.6.3",
+        "@suid/icons-material": "0.6.9",
         "@web-scrobbler/metadata-filter": "3.0.1",
         "blueimp-md5": "2.19.0",
         "stylelint": "13.13.1",
-        "vite": "4.3.9",
+        "vite": "4.4.8",
         "webextension-polyfill": "0.10.0"
       },
       "devDependencies": {
@@ -22,43 +22,52 @@
         "@types/fs-extra": "11.0.1",
         "@types/imagemin": "8.0.1",
         "@types/imagemin-jpegtran": "5.0.1",
-        "@types/node": "20.2.6",
-        "@types/react": "18.2.11",
-        "@types/webextension-polyfill": "0.10.0",
-        "@typescript-eslint/eslint-plugin": "5.59.9",
+        "@types/node": "20.4.8",
+        "@types/react": "18.2.18",
+        "@types/webextension-polyfill": "0.10.1",
+        "@typescript-eslint/eslint-plugin": "6.3.0",
         "archiver": "5.3.1",
         "canvas": "2.11.2",
         "chokidar": "3.5.3",
-        "esbuild": "0.18.0",
-        "eslint": "8.42.0",
+        "esbuild": "0.18.17",
+        "eslint": "8.46.0",
         "eslint-config-web-scrobbler": "2.1.1",
-        "eslint-plugin-react": "7.32.2",
+        "eslint-plugin-react": "7.33.1",
         "eslint-plugin-solid": "0.12.1",
         "eslint-plugin-tsdoc": "0.2.17",
         "fs-extra": "11.1.1",
-        "glob": "10.2.7",
+        "glob": "10.3.3",
         "imagemin": "8.0.1",
         "imagemin-jpegtran": "7.0.0",
         "imagemin-pngquant": "9.0.2",
-        "prettier": "2.8.8",
+        "prettier": "3.0.1",
         "prettier-config-web-scrobbler": "0.1.0",
         "remark": "14.0.3",
         "remark-cli": "11.0.0",
         "remark-preset-lint-recommended": "6.1.3",
-        "sass": "1.63.3",
-        "solid-js": "1.7.6",
+        "sass": "1.64.2",
+        "solid-js": "1.7.9",
         "stylelint-config-web-scrobbler": "0.2.0",
         "tsx": "3.12.7",
-        "typescript": "5.1.3",
+        "typescript": "5.1.6",
         "vite-plugin-conditional-compiler": "0.1.1",
         "vite-plugin-solid": "2.7.0",
-        "vite-plugin-static-copy": "0.16.0",
-        "vitest": "0.32.0"
+        "vite-plugin-static-copy": "0.17.0",
+        "vitest": "0.34.1"
       },
       "engines": {
         "node": ">=18.0.0"
       }
     },
+    "node_modules/@aashutoshrathi/word-wrap": {
+      "version": "1.2.6",
+      "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
+      "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/@ampproject/remapping": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
@@ -72,39 +81,39 @@
       }
     },
     "node_modules/@babel/code-frame": {
-      "version": "7.21.4",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz",
-      "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz",
+      "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==",
       "dependencies": {
-        "@babel/highlight": "^7.18.6"
+        "@babel/highlight": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/compat-data": {
-      "version": "7.21.4",
-      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz",
-      "integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.5.tgz",
+      "integrity": "sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==",
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/core": {
-      "version": "7.21.4",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz",
-      "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.5.tgz",
+      "integrity": "sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==",
       "dependencies": {
         "@ampproject/remapping": "^2.2.0",
-        "@babel/code-frame": "^7.21.4",
-        "@babel/generator": "^7.21.4",
-        "@babel/helper-compilation-targets": "^7.21.4",
-        "@babel/helper-module-transforms": "^7.21.2",
-        "@babel/helpers": "^7.21.0",
-        "@babel/parser": "^7.21.4",
-        "@babel/template": "^7.20.7",
-        "@babel/traverse": "^7.21.4",
-        "@babel/types": "^7.21.4",
+        "@babel/code-frame": "^7.22.5",
+        "@babel/generator": "^7.22.5",
+        "@babel/helper-compilation-targets": "^7.22.5",
+        "@babel/helper-module-transforms": "^7.22.5",
+        "@babel/helpers": "^7.22.5",
+        "@babel/parser": "^7.22.5",
+        "@babel/template": "^7.22.5",
+        "@babel/traverse": "^7.22.5",
+        "@babel/types": "^7.22.5",
         "convert-source-map": "^1.7.0",
         "debug": "^4.1.0",
         "gensync": "^1.0.0-beta.2",
@@ -120,19 +129,19 @@
       }
     },
     "node_modules/@babel/core/node_modules/semver": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-      "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
       "bin": {
         "semver": "bin/semver.js"
       }
     },
     "node_modules/@babel/generator": {
-      "version": "7.21.4",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz",
-      "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.5.tgz",
+      "integrity": "sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==",
       "dependencies": {
-        "@babel/types": "^7.21.4",
+        "@babel/types": "^7.22.5",
         "@jridgewell/gen-mapping": "^0.3.2",
         "@jridgewell/trace-mapping": "^0.3.17",
         "jsesc": "^2.5.1"
@@ -155,24 +164,24 @@
       }
     },
     "node_modules/@babel/helper-annotate-as-pure": {
-      "version": "7.18.6",
-      "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz",
-      "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
+      "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
       "dev": true,
       "dependencies": {
-        "@babel/types": "^7.18.6"
+        "@babel/types": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helper-compilation-targets": {
-      "version": "7.21.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz",
-      "integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz",
+      "integrity": "sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==",
       "dependencies": {
-        "@babel/compat-data": "^7.21.4",
-        "@babel/helper-validator-option": "^7.21.0",
+        "@babel/compat-data": "^7.22.5",
+        "@babel/helper-validator-option": "^7.22.5",
         "browserslist": "^4.21.3",
         "lru-cache": "^5.1.1",
         "semver": "^6.3.0"
@@ -193,9 +202,9 @@
       }
     },
     "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-      "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
       "bin": {
         "semver": "bin/semver.js"
       }
@@ -206,19 +215,20 @@
       "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
     },
     "node_modules/@babel/helper-create-class-features-plugin": {
-      "version": "7.21.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.4.tgz",
-      "integrity": "sha512-46QrX2CQlaFRF4TkwfTt6nJD7IHq8539cCL7SDpqWSDeJKY1xylKKY5F/33mJhLZ3mFvKv2gGrVS6NkyF6qs+Q==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-annotate-as-pure": "^7.18.6",
-        "@babel/helper-environment-visitor": "^7.18.9",
-        "@babel/helper-function-name": "^7.21.0",
-        "@babel/helper-member-expression-to-functions": "^7.21.0",
-        "@babel/helper-optimise-call-expression": "^7.18.6",
-        "@babel/helper-replace-supers": "^7.20.7",
-        "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0",
-        "@babel/helper-split-export-declaration": "^7.18.6"
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.5.tgz",
+      "integrity": "sha512-xkb58MyOYIslxu3gKmVXmjTtUPvBU4odYzbiIQbWwLKIHCsx6UGZGX6F1IznMFVnDdirseUZopzN+ZRt8Xb33Q==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-annotate-as-pure": "^7.22.5",
+        "@babel/helper-environment-visitor": "^7.22.5",
+        "@babel/helper-function-name": "^7.22.5",
+        "@babel/helper-member-expression-to-functions": "^7.22.5",
+        "@babel/helper-optimise-call-expression": "^7.22.5",
+        "@babel/helper-replace-supers": "^7.22.5",
+        "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
+        "@babel/helper-split-export-declaration": "^7.22.5",
+        "semver": "^6.3.0"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -227,193 +237,202 @@
         "@babel/core": "^7.0.0"
       }
     },
+    "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
     "node_modules/@babel/helper-environment-visitor": {
-      "version": "7.18.9",
-      "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
-      "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
+      "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==",
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helper-function-name": {
-      "version": "7.21.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz",
-      "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
+      "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
       "dependencies": {
-        "@babel/template": "^7.20.7",
-        "@babel/types": "^7.21.0"
+        "@babel/template": "^7.22.5",
+        "@babel/types": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helper-hoist-variables": {
-      "version": "7.18.6",
-      "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
-      "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
+      "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
       "dependencies": {
-        "@babel/types": "^7.18.6"
+        "@babel/types": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helper-member-expression-to-functions": {
-      "version": "7.21.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz",
-      "integrity": "sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz",
+      "integrity": "sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ==",
       "dev": true,
       "dependencies": {
-        "@babel/types": "^7.21.0"
+        "@babel/types": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helper-module-imports": {
-      "version": "7.21.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz",
-      "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz",
+      "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==",
       "dependencies": {
-        "@babel/types": "^7.21.4"
+        "@babel/types": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helper-module-transforms": {
-      "version": "7.21.2",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz",
-      "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz",
+      "integrity": "sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==",
       "dependencies": {
-        "@babel/helper-environment-visitor": "^7.18.9",
-        "@babel/helper-module-imports": "^7.18.6",
-        "@babel/helper-simple-access": "^7.20.2",
-        "@babel/helper-split-export-declaration": "^7.18.6",
-        "@babel/helper-validator-identifier": "^7.19.1",
-        "@babel/template": "^7.20.7",
-        "@babel/traverse": "^7.21.2",
-        "@babel/types": "^7.21.2"
+        "@babel/helper-environment-visitor": "^7.22.5",
+        "@babel/helper-module-imports": "^7.22.5",
+        "@babel/helper-simple-access": "^7.22.5",
+        "@babel/helper-split-export-declaration": "^7.22.5",
+        "@babel/helper-validator-identifier": "^7.22.5",
+        "@babel/template": "^7.22.5",
+        "@babel/traverse": "^7.22.5",
+        "@babel/types": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helper-optimise-call-expression": {
-      "version": "7.18.6",
-      "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz",
-      "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz",
+      "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==",
       "dev": true,
       "dependencies": {
-        "@babel/types": "^7.18.6"
+        "@babel/types": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helper-plugin-utils": {
-      "version": "7.20.2",
-      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz",
-      "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+      "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==",
       "dev": true,
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helper-replace-supers": {
-      "version": "7.20.7",
-      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz",
-      "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.5.tgz",
+      "integrity": "sha512-aLdNM5I3kdI/V9xGNyKSF3X/gTyMUBohTZ+/3QdQKAA9vxIiy12E+8E2HoOP1/DjeqU+g6as35QHJNMDDYpuCg==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-environment-visitor": "^7.18.9",
-        "@babel/helper-member-expression-to-functions": "^7.20.7",
-        "@babel/helper-optimise-call-expression": "^7.18.6",
-        "@babel/template": "^7.20.7",
-        "@babel/traverse": "^7.20.7",
-        "@babel/types": "^7.20.7"
+        "@babel/helper-environment-visitor": "^7.22.5",
+        "@babel/helper-member-expression-to-functions": "^7.22.5",
+        "@babel/helper-optimise-call-expression": "^7.22.5",
+        "@babel/template": "^7.22.5",
+        "@babel/traverse": "^7.22.5",
+        "@babel/types": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helper-simple-access": {
-      "version": "7.20.2",
-      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz",
-      "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
+      "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
       "dependencies": {
-        "@babel/types": "^7.20.2"
+        "@babel/types": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
-      "version": "7.20.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz",
-      "integrity": "sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz",
+      "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==",
       "dev": true,
       "dependencies": {
-        "@babel/types": "^7.20.0"
+        "@babel/types": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helper-split-export-declaration": {
-      "version": "7.18.6",
-      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
-      "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz",
+      "integrity": "sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==",
       "dependencies": {
-        "@babel/types": "^7.18.6"
+        "@babel/types": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helper-string-parser": {
-      "version": "7.19.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
-      "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
+      "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helper-validator-identifier": {
-      "version": "7.19.1",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
-      "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz",
+      "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==",
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helper-validator-option": {
-      "version": "7.21.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz",
-      "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz",
+      "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==",
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helpers": {
-      "version": "7.21.0",
-      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz",
-      "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.5.tgz",
+      "integrity": "sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==",
       "dependencies": {
-        "@babel/template": "^7.20.7",
-        "@babel/traverse": "^7.21.0",
-        "@babel/types": "^7.21.0"
+        "@babel/template": "^7.22.5",
+        "@babel/traverse": "^7.22.5",
+        "@babel/types": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/highlight": {
-      "version": "7.18.6",
-      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
-      "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz",
+      "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==",
       "dependencies": {
-        "@babel/helper-validator-identifier": "^7.18.6",
+        "@babel/helper-validator-identifier": "^7.22.5",
         "chalk": "^2.0.0",
         "js-tokens": "^4.0.0"
       },
@@ -486,9 +505,9 @@
       }
     },
     "node_modules/@babel/parser": {
-      "version": "7.21.4",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz",
-      "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz",
+      "integrity": "sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==",
       "bin": {
         "parser": "bin/babel-parser.js"
       },
@@ -497,12 +516,12 @@
       }
     },
     "node_modules/@babel/plugin-syntax-jsx": {
-      "version": "7.21.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz",
-      "integrity": "sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz",
+      "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-plugin-utils": "^7.20.2"
+        "@babel/helper-plugin-utils": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -512,12 +531,12 @@
       }
     },
     "node_modules/@babel/plugin-syntax-typescript": {
-      "version": "7.21.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.21.4.tgz",
-      "integrity": "sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz",
+      "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-plugin-utils": "^7.20.2"
+        "@babel/helper-plugin-utils": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -527,14 +546,14 @@
       }
     },
     "node_modules/@babel/plugin-transform-modules-commonjs": {
-      "version": "7.21.2",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz",
-      "integrity": "sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz",
+      "integrity": "sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-module-transforms": "^7.21.2",
-        "@babel/helper-plugin-utils": "^7.20.2",
-        "@babel/helper-simple-access": "^7.20.2"
+        "@babel/helper-module-transforms": "^7.22.5",
+        "@babel/helper-plugin-utils": "^7.22.5",
+        "@babel/helper-simple-access": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -544,15 +563,15 @@
       }
     },
     "node_modules/@babel/plugin-transform-typescript": {
-      "version": "7.21.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.21.3.tgz",
-      "integrity": "sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.5.tgz",
+      "integrity": "sha512-SMubA9S7Cb5sGSFFUlqxyClTA9zWJ8qGQrppNUm05LtFuN1ELRFNndkix4zUJrC9F+YivWwa1dHMSyo0e0N9dA==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-annotate-as-pure": "^7.18.6",
-        "@babel/helper-create-class-features-plugin": "^7.21.0",
-        "@babel/helper-plugin-utils": "^7.20.2",
-        "@babel/plugin-syntax-typescript": "^7.20.0"
+        "@babel/helper-annotate-as-pure": "^7.22.5",
+        "@babel/helper-create-class-features-plugin": "^7.22.5",
+        "@babel/helper-plugin-utils": "^7.22.5",
+        "@babel/plugin-syntax-typescript": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -562,16 +581,16 @@
       }
     },
     "node_modules/@babel/preset-typescript": {
-      "version": "7.21.4",
-      "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.21.4.tgz",
-      "integrity": "sha512-sMLNWY37TCdRH/bJ6ZeeOH1nPuanED7Ai9Y/vH31IPqalioJ6ZNFUWONsakhv4r4n+I6gm5lmoE0olkgib/j/A==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.22.5.tgz",
+      "integrity": "sha512-YbPaal9LxztSGhmndR46FmAbkJ/1fAsw293tSU+I5E5h+cnJ3d4GTwyUgGYmOXJYdGA+uNePle4qbaRzj2NISQ==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-plugin-utils": "^7.20.2",
-        "@babel/helper-validator-option": "^7.21.0",
-        "@babel/plugin-syntax-jsx": "^7.21.4",
-        "@babel/plugin-transform-modules-commonjs": "^7.21.2",
-        "@babel/plugin-transform-typescript": "^7.21.3"
+        "@babel/helper-plugin-utils": "^7.22.5",
+        "@babel/helper-validator-option": "^7.22.5",
+        "@babel/plugin-syntax-jsx": "^7.22.5",
+        "@babel/plugin-transform-modules-commonjs": "^7.22.5",
+        "@babel/plugin-transform-typescript": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -581,31 +600,31 @@
       }
     },
     "node_modules/@babel/template": {
-      "version": "7.20.7",
-      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz",
-      "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz",
+      "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==",
       "dependencies": {
-        "@babel/code-frame": "^7.18.6",
-        "@babel/parser": "^7.20.7",
-        "@babel/types": "^7.20.7"
+        "@babel/code-frame": "^7.22.5",
+        "@babel/parser": "^7.22.5",
+        "@babel/types": "^7.22.5"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/traverse": {
-      "version": "7.21.4",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz",
-      "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==",
-      "dependencies": {
-        "@babel/code-frame": "^7.21.4",
-        "@babel/generator": "^7.21.4",
-        "@babel/helper-environment-visitor": "^7.18.9",
-        "@babel/helper-function-name": "^7.21.0",
-        "@babel/helper-hoist-variables": "^7.18.6",
-        "@babel/helper-split-export-declaration": "^7.18.6",
-        "@babel/parser": "^7.21.4",
-        "@babel/types": "^7.21.4",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.5.tgz",
+      "integrity": "sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==",
+      "dependencies": {
+        "@babel/code-frame": "^7.22.5",
+        "@babel/generator": "^7.22.5",
+        "@babel/helper-environment-visitor": "^7.22.5",
+        "@babel/helper-function-name": "^7.22.5",
+        "@babel/helper-hoist-variables": "^7.22.5",
+        "@babel/helper-split-export-declaration": "^7.22.5",
+        "@babel/parser": "^7.22.5",
+        "@babel/types": "^7.22.5",
         "debug": "^4.1.0",
         "globals": "^11.1.0"
       },
@@ -622,12 +641,12 @@
       }
     },
     "node_modules/@babel/types": {
-      "version": "7.21.4",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz",
-      "integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz",
+      "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==",
       "dependencies": {
-        "@babel/helper-string-parser": "^7.19.4",
-        "@babel/helper-validator-identifier": "^7.19.1",
+        "@babel/helper-string-parser": "^7.22.5",
+        "@babel/helper-validator-identifier": "^7.22.5",
         "to-fast-properties": "^2.0.0"
       },
       "engines": {
@@ -1054,13 +1073,12 @@
       }
     },
     "node_modules/@esbuild/android-arm": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.0.tgz",
-      "integrity": "sha512-+uLHSiWK3qOeyDYCf/nuvIgCnQsYjXWNa3TlGYLW1pPG7OYMawllU+VyBgHQPjF2aIUVFpfrvz5aAfxGk/0qNg==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.17.tgz",
+      "integrity": "sha512-wHsmJG/dnL3OkpAcwbgoBTTMHVi4Uyou3F5mf58ZtmUyIKfcdA7TROav/6tCzET4A3QW2Q2FC+eFneMU+iyOxg==",
       "cpu": [
         "arm"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "android"
@@ -1070,13 +1088,12 @@
       }
     },
     "node_modules/@esbuild/android-arm64": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.0.tgz",
-      "integrity": "sha512-nAwRCs5+jxi3gBMVkOqmRvsITB/UtfpvkbMwAwJUIbp66NnPbV2KGCFnjNn7IEqabJQXfBLe/QLdjCGpHU+yEw==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.17.tgz",
+      "integrity": "sha512-9np+YYdNDed5+Jgr1TdWBsozZ85U1Oa3xW0c7TWqH0y2aGghXtZsuT8nYRbzOMcl0bXZXjOGbksoTtVOlWrRZg==",
       "cpu": [
         "arm64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "android"
@@ -1086,13 +1103,12 @@
       }
     },
     "node_modules/@esbuild/android-x64": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.0.tgz",
-      "integrity": "sha512-TiOJmHQ8bXCGlYLpBd3Qy7N8dxi4n6q+nOmTzPr5Hb/bUr+PKuP4e5lWaOlpkaKc1Q9wsFt+sHfQpFCrM7SMow==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.17.tgz",
+      "integrity": "sha512-O+FeWB/+xya0aLg23hHEM2E3hbfwZzjqumKMSIqcHbNvDa+dza2D0yLuymRBQQnC34CWrsJUXyH2MG5VnLd6uw==",
       "cpu": [
         "x64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "android"
@@ -1102,13 +1118,12 @@
       }
     },
     "node_modules/@esbuild/darwin-arm64": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.0.tgz",
-      "integrity": "sha512-5GsFovtGyjMIXJrcCzmI1hX3TneCrmFncFIlo0WrRvWcVU6H094P854ZaP8qoLgevXhggO2dhlEGYY0Zv6/S9Q==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.17.tgz",
+      "integrity": "sha512-M9uJ9VSB1oli2BE/dJs3zVr9kcCBBsE883prage1NWz6pBS++1oNn/7soPNS3+1DGj0FrkSvnED4Bmlu1VAE9g==",
       "cpu": [
         "arm64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "darwin"
@@ -1118,13 +1133,12 @@
       }
     },
     "node_modules/@esbuild/darwin-x64": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.0.tgz",
-      "integrity": "sha512-4K/QCksQ8F58rvC1D62Xi4q4E7YWpiyc3zy2H/n1W7y0hjQpOBBxciLn0qycMskP/m/I5h9HNbRlu1aK821sHg==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.17.tgz",
+      "integrity": "sha512-XDre+J5YeIJDMfp3n0279DFNrGCXlxOuGsWIkRb1NThMZ0BsrWXoTg23Jer7fEXQ9Ye5QjrvXpxnhzl3bHtk0g==",
       "cpu": [
         "x64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "darwin"
@@ -1134,13 +1148,12 @@
       }
     },
     "node_modules/@esbuild/freebsd-arm64": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.0.tgz",
-      "integrity": "sha512-DMazN0UGzipD0Fi1O9pRX0xfp+JC3gSnFWxTWq88Dr/odWhZzm8Jqy44LN2veYeipb1fBMxhoEp7eCr902SWqg==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.17.tgz",
+      "integrity": "sha512-cjTzGa3QlNfERa0+ptykyxs5A6FEUQQF0MuilYXYBGdBxD3vxJcKnzDlhDCa1VAJCmAxed6mYhA2KaJIbtiNuQ==",
       "cpu": [
         "arm64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "freebsd"
@@ -1150,13 +1163,12 @@
       }
     },
     "node_modules/@esbuild/freebsd-x64": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.0.tgz",
-      "integrity": "sha512-GdkJAB3ZBiYnie9iFO9v/CM4ko0dm5SYkUs97lBKNLHw9mo4H9IXwGNKtUztisEsmUP0IWfEi4YTWOJF3DIO4w==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.17.tgz",
+      "integrity": "sha512-sOxEvR8d7V7Kw8QqzxWc7bFfnWnGdaFBut1dRUYtu+EIRXefBc/eIsiUiShnW0hM3FmQ5Zf27suDuHsKgZ5QrA==",
       "cpu": [
         "x64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "freebsd"
@@ -1166,13 +1178,12 @@
       }
     },
     "node_modules/@esbuild/linux-arm": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.0.tgz",
-      "integrity": "sha512-A3Ue/oZdb43znNpeY71FrAjZF20MtnBKCGb1vXLIVg5qg8rRM1gRgn6X2ixYwATiw5dE04JnP+aV4OBf8c5ZvQ==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.17.tgz",
+      "integrity": "sha512-2d3Lw6wkwgSLC2fIvXKoMNGVaeY8qdN0IC3rfuVxJp89CRfA3e3VqWifGDfuakPmp90+ZirmTfye1n4ncjv2lg==",
       "cpu": [
         "arm"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "linux"
@@ -1182,13 +1193,12 @@
       }
     },
     "node_modules/@esbuild/linux-arm64": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.0.tgz",
-      "integrity": "sha512-Mb3yCN9PXA6G5qf84UF0IEuXP22eyNlquF17Zs2F1vVBM0CtyWLYosC5JaxBxfK6EzWwB2IkPBIjMeK3ek+ItA==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.17.tgz",
+      "integrity": "sha512-c9w3tE7qA3CYWjT+M3BMbwMt+0JYOp3vCMKgVBrCl1nwjAlOMYzEo+gG7QaZ9AtqZFj5MbUc885wuBBmu6aADQ==",
       "cpu": [
         "arm64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "linux"
@@ -1198,13 +1208,12 @@
       }
     },
     "node_modules/@esbuild/linux-ia32": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.0.tgz",
-      "integrity": "sha512-WNDXgJdfDhN6ZxHU7HgR2BRDVx9iGN8SpmebUUGdENg4MZJndGcaQuf2kCJjMwoK0+es1g61TeJzAMxfgDcmcA==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.17.tgz",
+      "integrity": "sha512-1DS9F966pn5pPnqXYz16dQqWIB0dmDfAQZd6jSSpiT9eX1NzKh07J6VKR3AoXXXEk6CqZMojiVDSZi1SlmKVdg==",
       "cpu": [
         "ia32"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "linux"
@@ -1214,13 +1223,12 @@
       }
     },
     "node_modules/@esbuild/linux-loong64": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.0.tgz",
-      "integrity": "sha512-PBr8Lf+L8amvheTGFVNK/0qionszkOKMq2WyfFlVz8D41v0+uSth6fYYHwtASkMk4xf+oh0vW8NYuav3/3RHuQ==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.17.tgz",
+      "integrity": "sha512-EvLsxCk6ZF0fpCB6w6eOI2Fc8KW5N6sHlIovNe8uOFObL2O+Mr0bflPHyHwLT6rwMg9r77WOAWb2FqCQrVnwFg==",
       "cpu": [
         "loong64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "linux"
@@ -1230,13 +1238,12 @@
       }
     },
     "node_modules/@esbuild/linux-mips64el": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.0.tgz",
-      "integrity": "sha512-Lg4ygah5bwfDDCOMFsBJjSVbD1UzNwWt4f7DhpaSIFOrJqoECX1VTByKw3iSDAVRlwl1cljlfy7wlysrRZcdiQ==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.17.tgz",
+      "integrity": "sha512-e0bIdHA5p6l+lwqTE36NAW5hHtw2tNRmHlGBygZC14QObsA3bD4C6sXLJjvnDIjSKhW1/0S3eDy+QmX/uZWEYQ==",
       "cpu": [
         "mips64el"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "linux"
@@ -1246,13 +1253,12 @@
       }
     },
     "node_modules/@esbuild/linux-ppc64": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.0.tgz",
-      "integrity": "sha512-obz/firdtou244DIjHzdKmJChwGseqA3tWGa6xPMfuq54Ca4Pp1a4ANMrqy2IZ67rfpRHcJTlb2h3rSfW6tvAA==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.17.tgz",
+      "integrity": "sha512-BAAilJ0M5O2uMxHYGjFKn4nJKF6fNCdP1E0o5t5fvMYYzeIqy2JdAP88Az5LHt9qBoUa4tDaRpfWt21ep5/WqQ==",
       "cpu": [
         "ppc64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "linux"
@@ -1262,13 +1268,12 @@
       }
     },
     "node_modules/@esbuild/linux-riscv64": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.0.tgz",
-      "integrity": "sha512-UkuBdxQsxi39wWrRLMOkJl//82/hpQw79TD+OBLw3IBYyVQ4Wfvpe56RfEGK/j439sIm79ccnD5RUNQceHvZdQ==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.17.tgz",
+      "integrity": "sha512-Wh/HW2MPnC3b8BqRSIme/9Zhab36PPH+3zam5pqGRH4pE+4xTrVLx2+XdGp6fVS3L2x+DrsIcsbMleex8fbE6g==",
       "cpu": [
         "riscv64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "linux"
@@ -1278,13 +1283,12 @@
       }
     },
     "node_modules/@esbuild/linux-s390x": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.0.tgz",
-      "integrity": "sha512-MgyuC30oYB465hyAqsb3EH6Y4zTeqqgixRAOpsDNMCelyDiW9ZDPXvMPfBgCZGJlDZFGKDm2I9ou8E3VI+v7pg==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.17.tgz",
+      "integrity": "sha512-j/34jAl3ul3PNcK3pfI0NSlBANduT2UO5kZ7FCaK33XFv3chDhICLY8wJJWIhiQ+YNdQ9dxqQctRg2bvrMlYgg==",
       "cpu": [
         "s390x"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "linux"
@@ -1294,13 +1298,12 @@
       }
     },
     "node_modules/@esbuild/linux-x64": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.0.tgz",
-      "integrity": "sha512-oLLKU3F4pKWAsNmfi7Rd4qkj0qvg1S923ZjlcISA2IMgHsODA9xzwerqWayI5nOhLGgKXviDofn9exTeA4EUQQ==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.17.tgz",
+      "integrity": "sha512-QM50vJ/y+8I60qEmFxMoxIx4de03pGo2HwxdBeFd4nMh364X6TIBZ6VQ5UQmPbQWUVWHWws5MmJXlHAXvJEmpQ==",
       "cpu": [
         "x64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "linux"
@@ -1310,13 +1313,12 @@
       }
     },
     "node_modules/@esbuild/netbsd-x64": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.0.tgz",
-      "integrity": "sha512-BEfJrZsZ/gMtpS2vC+2YoFGxmfLKiYQvj8lZrBfjKzQrwyMpH53CzQJj9ypOx9ldjM/MVxf9i9wi/rS4BWV7WA==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.17.tgz",
+      "integrity": "sha512-/jGlhWR7Sj9JPZHzXyyMZ1RFMkNPjC6QIAan0sDOtIo2TYk3tZn5UDrkE0XgsTQCxWTTOcMPf9p6Rh2hXtl5TQ==",
       "cpu": [
         "x64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "netbsd"
@@ -1326,13 +1328,12 @@
       }
     },
     "node_modules/@esbuild/openbsd-x64": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.0.tgz",
-      "integrity": "sha512-eDolHeG3REnEIgwl7Lw2S0znUMY4PFVtCAzLKqdRO0HD+iPKJR8n2MEJJyhPdUjcobo8SEQ2AG6gtYfft9VFHg==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.17.tgz",
+      "integrity": "sha512-rSEeYaGgyGGf4qZM2NonMhMOP/5EHp4u9ehFiBrg7stH6BYEEjlkVREuDEcQ0LfIl53OXLxNbfuIj7mr5m29TA==",
       "cpu": [
         "x64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "openbsd"
@@ -1342,13 +1343,12 @@
       }
     },
     "node_modules/@esbuild/sunos-x64": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.0.tgz",
-      "integrity": "sha512-kl7vONem2wmRQke015rSrknmc6TYXKVNs2quiVTdvkSufscrjegpNqKyP7v6EHqXtvkzrB92ySjpfzazKG627g==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.17.tgz",
+      "integrity": "sha512-Y7ZBbkLqlSgn4+zot4KUNYst0bFoO68tRgI6mY2FIM+b7ZbyNVtNbDP5y8qlu4/knZZ73fgJDlXID+ohY5zt5g==",
       "cpu": [
         "x64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "sunos"
@@ -1358,13 +1358,12 @@
       }
     },
     "node_modules/@esbuild/win32-arm64": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.0.tgz",
-      "integrity": "sha512-WohArFQ3HStBu9MAsx3JUk2wfC2v8QoadnMoNfx3Y26ac54tD/wQhPzw4QOzQbSqOFqzIMLKWbxindTsko+9OA==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.17.tgz",
+      "integrity": "sha512-bwPmTJsEQcbZk26oYpc4c/8PvTY3J5/QK8jM19DVlEsAB41M39aWovWoHtNm78sd6ip6prilxeHosPADXtEJFw==",
       "cpu": [
         "arm64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "win32"
@@ -1374,13 +1373,12 @@
       }
     },
     "node_modules/@esbuild/win32-ia32": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.0.tgz",
-      "integrity": "sha512-SdnpSOxpeoewYCurmfLVepLuhOAphWkGTxWHifFjp37DaUHwF1fpGzyxhZoXMt5MKGuAO5aE3c5668YYtno+9Q==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.17.tgz",
+      "integrity": "sha512-H/XaPtPKli2MhW+3CQueo6Ni3Avggi6hP/YvgkEe1aSaxw+AeO8MFjq8DlgfTd9Iz4Yih3QCZI6YLMoyccnPRg==",
       "cpu": [
         "ia32"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "win32"
@@ -1390,13 +1388,12 @@
       }
     },
     "node_modules/@esbuild/win32-x64": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.0.tgz",
-      "integrity": "sha512-WJxImv0Pehpbo+pgg7Xrn88/b6ZzSweNHTw/2LW95JjeQUIS6ToJeQmjAdud9H3yiHJmhLOmEAOvUdNLhptD0w==",
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.17.tgz",
+      "integrity": "sha512-fGEb8f2BSA3CW7riJVurug65ACLuQAzKq0SSqkY2b2yHHH0MzDfbLyKIGzHwOI/gkHcxM/leuSW6D5w/LMNitA==",
       "cpu": [
         "x64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "win32"
@@ -1421,23 +1418,23 @@
       }
     },
     "node_modules/@eslint-community/regexpp": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.0.tgz",
-      "integrity": "sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==",
+      "version": "4.6.2",
+      "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz",
+      "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==",
       "dev": true,
       "engines": {
         "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
       }
     },
     "node_modules/@eslint/eslintrc": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz",
-      "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==",
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.1.tgz",
+      "integrity": "sha512-9t7ZA7NGGK8ckelF0PQCfcxIUzs1Md5rrO6U/c+FIQNanea5UZC0wqKXH4vHBccmu4ZJgZ2idtPeW7+Q2npOEA==",
       "dev": true,
       "dependencies": {
         "ajv": "^6.12.4",
         "debug": "^4.3.2",
-        "espree": "^9.5.2",
+        "espree": "^9.6.0",
         "globals": "^13.19.0",
         "ignore": "^5.2.0",
         "import-fresh": "^3.2.1",
@@ -1453,9 +1450,9 @@
       }
     },
     "node_modules/@eslint/js": {
-      "version": "8.42.0",
-      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz",
-      "integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==",
+      "version": "8.46.0",
+      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.46.0.tgz",
+      "integrity": "sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA==",
       "dev": true,
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1494,6 +1491,18 @@
       "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
       "dev": true
     },
+    "node_modules/@jest/schemas": {
+      "version": "29.6.0",
+      "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz",
+      "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==",
+      "dev": true,
+      "dependencies": {
+        "@sinclair/typebox": "^0.27.8"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
     "node_modules/@jridgewell/gen-mapping": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
@@ -1578,9 +1587,9 @@
       }
     },
     "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir/node_modules/semver": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-      "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
       "dev": true,
       "bin": {
         "semver": "bin/semver.js"
@@ -1791,6 +1800,12 @@
         "url": "https://opencollective.com/popperjs"
       }
     },
+    "node_modules/@sinclair/typebox": {
+      "version": "0.27.8",
+      "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
+      "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
+      "dev": true
+    },
     "node_modules/@sindresorhus/is": {
       "version": "0.7.0",
       "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz",
@@ -2028,98 +2043,98 @@
       }
     },
     "node_modules/@suid/base": {
-      "version": "0.8.2",
-      "resolved": "https://registry.npmjs.org/@suid/base/-/base-0.8.2.tgz",
-      "integrity": "sha512-saue6/ss0ylDMz2mOK6kKvxBqkt5wCNTOutsQ6oi+zeeKXp+0SRpfhqmhhBWZw9s00eq+qE17G4ln2yvZ7d9ug==",
+      "version": "0.8.4",
+      "resolved": "https://registry.npmjs.org/@suid/base/-/base-0.8.4.tgz",
+      "integrity": "sha512-LSsqYVx3D3GSRUgVpZ5gaJec0JY2q1N2ZTzradQeoteEmdb+qG6ltXBik/lfaMn/+QOkO+ROyc2H4vlCTKlZaA==",
       "dependencies": {
         "@popperjs/core": "^2.11.7",
-        "@suid/css": "0.3.1",
-        "@suid/system": "0.10.2",
-        "@suid/types": "0.5.1",
-        "@suid/utils": "0.7.2",
+        "@suid/css": "0.4.0",
+        "@suid/system": "0.10.4",
+        "@suid/types": "0.5.2",
+        "@suid/utils": "0.7.3",
         "clsx": "^1.2.1"
       },
       "peerDependencies": {
-        "solid-js": "^1.7.5"
+        "solid-js": "^1.7.7"
       }
     },
     "node_modules/@suid/css": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/@suid/css/-/css-0.3.1.tgz",
-      "integrity": "sha512-OXUgCwKvMy6rIu+tcRybKxFzCBbwaEXG30MmCV26uzwhTxYcmSXU4tdiTenpAD7w1VS0Xysw0pf+tGtzKIMX8g=="
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/@suid/css/-/css-0.4.0.tgz",
+      "integrity": "sha512-yzHAlf1CVi7n0SvUrMgs8Z49UiS9669+td1w1frekhRQuRbkXhHoyJkvovaDVJlWRmCPA8Q0f1OTr0uDCUg9mQ=="
     },
     "node_modules/@suid/icons-material": {
-      "version": "0.6.3",
-      "resolved": "https://registry.npmjs.org/@suid/icons-material/-/icons-material-0.6.3.tgz",
-      "integrity": "sha512-FunY1jtCdXpBr9hL0CCvJB+dthyYumjqvpj+w/Oln/qfxOsWnjH/QFsqEYaCVJSyFWhchSdBJXCGEsb/fEsFRw==",
+      "version": "0.6.9",
+      "resolved": "https://registry.npmjs.org/@suid/icons-material/-/icons-material-0.6.9.tgz",
+      "integrity": "sha512-qiKVwfhati4tDFPBLa0ad8R9xpXEgwFlec6PO1vBQVSnAEdIVh7j4I8pjbe1UyK91wi/p+deM1kBrhwOejS9Uw==",
       "dependencies": {
-        "@suid/material": "0.12.3"
+        "@suid/material": "0.14.2"
       },
       "peerDependencies": {
-        "solid-js": "^1.7.5"
+        "solid-js": "^1.7.7"
       }
     },
     "node_modules/@suid/material": {
-      "version": "0.12.3",
-      "resolved": "https://registry.npmjs.org/@suid/material/-/material-0.12.3.tgz",
-      "integrity": "sha512-Kcq+HNO6U0rBLfhHRHwsKSQckDqN6Z5qguQWBCn11VlgOWrurG+0ZJVVYi47nTt71w2eb4eyQBneveEO4EdeYQ==",
-      "dependencies": {
-        "@suid/base": "0.8.2",
-        "@suid/css": "0.3.1",
-        "@suid/system": "0.10.2",
-        "@suid/types": "0.5.1",
-        "@suid/utils": "0.7.2",
+      "version": "0.14.2",
+      "resolved": "https://registry.npmjs.org/@suid/material/-/material-0.14.2.tgz",
+      "integrity": "sha512-VdYX4xC0aA+SL9DcSM1uz198Z+UJQiuvNZfK6IOyoDbdQatZJ1+zqpqUWeICdX/5krLq9rs7OBAxsjNNYkwIhA==",
+      "dependencies": {
+        "@suid/base": "0.8.4",
+        "@suid/css": "0.4.0",
+        "@suid/system": "0.10.4",
+        "@suid/types": "0.5.2",
+        "@suid/utils": "0.7.3",
         "clsx": "^1.2.1"
       },
       "peerDependencies": {
-        "solid-js": "^1.7.5"
+        "solid-js": "^1.7.7"
       }
     },
     "node_modules/@suid/styled-engine": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/@suid/styled-engine/-/styled-engine-0.5.2.tgz",
-      "integrity": "sha512-PVUrs3K0iaXNy2wwiFr9MSGv4Kkvq0HPI6kFdHTwY44u0zZiTqBeZe9dTmmTjfxmiJj0AofzUqU7+HqasDALvw==",
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/@suid/styled-engine/-/styled-engine-0.6.0.tgz",
+      "integrity": "sha512-xQPkjRSlWViOK/S6szET4d0SscupX6SyOq9Sc3L8X1ttdZUleUYPE4Kl+jBfAcxRkPssxXQS+fNv1DDxNaAZzA==",
       "dependencies": {
-        "@suid/css": "0.3.1",
-        "@suid/utils": "0.7.2"
+        "@suid/css": "0.4.0",
+        "@suid/utils": "0.7.3"
       },
       "peerDependencies": {
-        "solid-js": "^1.7.5"
+        "solid-js": "^1.7.7"
       }
     },
     "node_modules/@suid/system": {
-      "version": "0.10.2",
-      "resolved": "https://registry.npmjs.org/@suid/system/-/system-0.10.2.tgz",
-      "integrity": "sha512-af7LJDS6Z7EM1x9FludSQDjATxsxtC6sYwpYrjuH+bIkArAKkHYNGc2dDl9SCJ1fOeEIiIKMiWbPnMQ1Pobznw==",
-      "dependencies": {
-        "@suid/css": "0.3.1",
-        "@suid/styled-engine": "0.5.2",
-        "@suid/types": "0.5.1",
-        "@suid/utils": "0.7.2",
+      "version": "0.10.4",
+      "resolved": "https://registry.npmjs.org/@suid/system/-/system-0.10.4.tgz",
+      "integrity": "sha512-kVf1b0In5ZOOMLXodXRT+ro662H/wiVzsRvtT5hHN6El1WnLDuoij64+7A9UK/zCXsqgmaI5VFFQnple8O97eQ==",
+      "dependencies": {
+        "@suid/css": "0.4.0",
+        "@suid/styled-engine": "0.6.0",
+        "@suid/types": "0.5.2",
+        "@suid/utils": "0.7.3",
         "clsx": "^1.2.1",
         "csstype": "^3.1.2"
       },
       "peerDependencies": {
-        "solid-js": "^1.7.5"
+        "solid-js": "^1.7.7"
       }
     },
     "node_modules/@suid/types": {
-      "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/@suid/types/-/types-0.5.1.tgz",
-      "integrity": "sha512-5Cg/n5Z6veyMdkVXlK32xX+uBawaVeLbnqRhJl/zU5uSWuC5hP7g08Rm3FJ7pH48nvDMlwx7CsIDUWRnGYczag==",
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/@suid/types/-/types-0.5.2.tgz",
+      "integrity": "sha512-//MI7gmqebLkVK4mUonrowoEG/YNkZ+/aGcSU1FHZLXg7vCPoGdP4A/YNqYIKPthw2ybbsXDvA2ln7AEfDrdxA==",
       "peerDependencies": {
-        "solid-js": "^1.7.5"
+        "solid-js": "^1.7.7"
       }
     },
     "node_modules/@suid/utils": {
-      "version": "0.7.2",
-      "resolved": "https://registry.npmjs.org/@suid/utils/-/utils-0.7.2.tgz",
-      "integrity": "sha512-NVOYWEGFnY2TaVuY/5F+HxtTE4G6HYfag1+/XMEkyYrZlTjrubDQ2GnWW0NIcKnreO0Fq+vxineBWA76HVNHcw==",
+      "version": "0.7.3",
+      "resolved": "https://registry.npmjs.org/@suid/utils/-/utils-0.7.3.tgz",
+      "integrity": "sha512-ip3ppEUqITm37soIvRHmJgrvzw3XbjTKcF5Kj9BweSAL+UuHIrmJBGQqgS7Rt/Ou2gb3281XX4xgX/exprIAaA==",
       "dependencies": {
-        "@suid/types": "0.5.1"
+        "@suid/types": "0.5.2"
       },
       "peerDependencies": {
-        "solid-js": "^1.7.5"
+        "solid-js": "^1.7.7"
       }
     },
     "node_modules/@tokenizer/token": {
@@ -2276,9 +2291,9 @@
       "dev": true
     },
     "node_modules/@types/json-schema": {
-      "version": "7.0.11",
-      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
-      "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
+      "version": "7.0.12",
+      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz",
+      "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==",
       "dev": true
     },
     "node_modules/@types/jsonfile": {
@@ -2310,9 +2325,9 @@
       "dev": true
     },
     "node_modules/@types/node": {
-      "version": "20.2.6",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.6.tgz",
-      "integrity": "sha512-GQBWUtGoefMEOx/vu+emHEHU5aw6JdDoEtZhoBrHFPZbA/YNRFfN996XbBASEWdvmLSLyv9FKYppYGyZjCaq/g==",
+      "version": "20.4.8",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.8.tgz",
+      "integrity": "sha512-0mHckf6D2DiIAzh8fM8f3HQCvMKDpK94YQ0DSVkfWTG9BZleYIWudw9cJxX8oCk9bM+vAkDyujDV6dmKHbvQpg==",
       "devOptional": true
     },
     "node_modules/@types/normalize-package-data": {
@@ -2332,9 +2347,9 @@
       "dev": true
     },
     "node_modules/@types/react": {
-      "version": "18.2.11",
-      "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.11.tgz",
-      "integrity": "sha512-+hsJr9hmwyDecSMQAmX7drgbDpyE+EgSF6t7+5QEBAn1tQK7kl1vWZ4iRf6SjQ8lk7dyEULxUmZOIpN0W5baZA==",
+      "version": "18.2.18",
+      "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.18.tgz",
+      "integrity": "sha512-da4NTSeBv/P34xoZPhtcLkmZuJ+oYaCxHmyHzwaDQo9RQPBeXV+06gEk2FpqEcsX9XrnNLvRpVh6bdavDSjtiQ==",
       "dev": true,
       "dependencies": {
         "@types/prop-types": "*",
@@ -2358,9 +2373,9 @@
       "dev": true
     },
     "node_modules/@types/semver": {
-      "version": "7.3.13",
-      "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
-      "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
+      "version": "7.5.0",
+      "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz",
+      "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==",
       "dev": true
     },
     "node_modules/@types/supports-color": {
@@ -2381,38 +2396,40 @@
       "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ=="
     },
     "node_modules/@types/webextension-polyfill": {
-      "version": "0.10.0",
-      "resolved": "https://registry.npmjs.org/@types/webextension-polyfill/-/webextension-polyfill-0.10.0.tgz",
-      "integrity": "sha512-If4EcaHzYTqcbNMp/FdReVdRmLL/Te42ivnJII551bYjhX19bWem5m14FERCqdJA732OloGuxCRvLBvcMGsn4A==",
+      "version": "0.10.1",
+      "resolved": "https://registry.npmjs.org/@types/webextension-polyfill/-/webextension-polyfill-0.10.1.tgz",
+      "integrity": "sha512-Sdg+E2F5JUbhkE1qX15QUxpyhfMFKRGJqND9nb1C0gNN4NR7kCV31/1GvNbg6Xe+m/JElJ9/lG5kepMzjGPuQw==",
       "dev": true
     },
     "node_modules/@typescript-eslint/eslint-plugin": {
-      "version": "5.59.9",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.9.tgz",
-      "integrity": "sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA==",
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.3.0.tgz",
+      "integrity": "sha512-IZYjYZ0ifGSLZbwMqIip/nOamFiWJ9AH+T/GYNZBWkVcyNQOFGtSMoWV7RvY4poYCMZ/4lHzNl796WOSNxmk8A==",
       "dev": true,
       "dependencies": {
-        "@eslint-community/regexpp": "^4.4.0",
-        "@typescript-eslint/scope-manager": "5.59.9",
-        "@typescript-eslint/type-utils": "5.59.9",
-        "@typescript-eslint/utils": "5.59.9",
+        "@eslint-community/regexpp": "^4.5.1",
+        "@typescript-eslint/scope-manager": "6.3.0",
+        "@typescript-eslint/type-utils": "6.3.0",
+        "@typescript-eslint/utils": "6.3.0",
+        "@typescript-eslint/visitor-keys": "6.3.0",
         "debug": "^4.3.4",
-        "grapheme-splitter": "^1.0.4",
-        "ignore": "^5.2.0",
+        "graphemer": "^1.4.0",
+        "ignore": "^5.2.4",
+        "natural-compare": "^1.4.0",
         "natural-compare-lite": "^1.4.0",
-        "semver": "^7.3.7",
-        "tsutils": "^3.21.0"
+        "semver": "^7.5.4",
+        "ts-api-utils": "^1.0.1"
       },
       "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+        "node": "^16.0.0 || >=18.0.0"
       },
       "funding": {
         "type": "opencollective",
         "url": "https://opencollective.com/typescript-eslint"
       },
       "peerDependencies": {
-        "@typescript-eslint/parser": "^5.0.0",
-        "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+        "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
+        "eslint": "^7.0.0 || ^8.0.0"
       },
       "peerDependenciesMeta": {
         "typescript": {
@@ -2420,27 +2437,87 @@
         }
       }
     },
+    "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": {
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.3.0.tgz",
+      "integrity": "sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==",
+      "dev": true,
+      "dependencies": {
+        "@typescript-eslint/types": "6.3.0",
+        "@typescript-eslint/visitor-keys": "6.3.0"
+      },
+      "engines": {
+        "node": "^16.0.0 || >=18.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": {
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.3.0.tgz",
+      "integrity": "sha512-hLLg3BZE07XHnpzglNBG8P/IXq/ZVXraEbgY7FM0Cnc1ehM8RMdn9mat3LubJ3KBeYXXPxV1nugWbQPjGeJk6Q==",
+      "dev": true,
+      "dependencies": {
+        "@eslint-community/eslint-utils": "^4.4.0",
+        "@types/json-schema": "^7.0.12",
+        "@types/semver": "^7.5.0",
+        "@typescript-eslint/scope-manager": "6.3.0",
+        "@typescript-eslint/types": "6.3.0",
+        "@typescript-eslint/typescript-estree": "6.3.0",
+        "semver": "^7.5.4"
+      },
+      "engines": {
+        "node": "^16.0.0 || >=18.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^7.0.0 || ^8.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": {
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz",
+      "integrity": "sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==",
+      "dev": true,
+      "dependencies": {
+        "@typescript-eslint/types": "6.3.0",
+        "eslint-visitor-keys": "^3.4.1"
+      },
+      "engines": {
+        "node": "^16.0.0 || >=18.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
     "node_modules/@typescript-eslint/parser": {
-      "version": "5.57.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.57.1.tgz",
-      "integrity": "sha512-hlA0BLeVSA/wBPKdPGxoVr9Pp6GutGoY380FEhbVi0Ph4WNe8kLvqIRx76RSQt1lynZKfrXKs0/XeEk4zZycuA==",
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.3.0.tgz",
+      "integrity": "sha512-ibP+y2Gr6p0qsUkhs7InMdXrwldjxZw66wpcQq9/PzAroM45wdwyu81T+7RibNCh8oc0AgrsyCwJByncY0Ongg==",
       "dev": true,
       "peer": true,
       "dependencies": {
-        "@typescript-eslint/scope-manager": "5.57.1",
-        "@typescript-eslint/types": "5.57.1",
-        "@typescript-eslint/typescript-estree": "5.57.1",
+        "@typescript-eslint/scope-manager": "6.3.0",
+        "@typescript-eslint/types": "6.3.0",
+        "@typescript-eslint/typescript-estree": "6.3.0",
+        "@typescript-eslint/visitor-keys": "6.3.0",
         "debug": "^4.3.4"
       },
       "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+        "node": "^16.0.0 || >=18.0.0"
       },
       "funding": {
         "type": "opencollective",
         "url": "https://opencollective.com/typescript-eslint"
       },
       "peerDependencies": {
-        "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+        "eslint": "^7.0.0 || ^8.0.0"
       },
       "peerDependenciesMeta": {
         "typescript": {
@@ -2449,17 +2526,17 @@
       }
     },
     "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
-      "version": "5.57.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.57.1.tgz",
-      "integrity": "sha512-N/RrBwEUKMIYxSKl0oDK5sFVHd6VI7p9K5MyUlVYAY6dyNb/wHUqndkTd3XhpGlXgnQsBkRZuu4f9kAHghvgPw==",
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.3.0.tgz",
+      "integrity": "sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==",
       "dev": true,
       "peer": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.57.1",
-        "@typescript-eslint/visitor-keys": "5.57.1"
+        "@typescript-eslint/types": "6.3.0",
+        "@typescript-eslint/visitor-keys": "6.3.0"
       },
       "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+        "node": "^16.0.0 || >=18.0.0"
       },
       "funding": {
         "type": "opencollective",
@@ -2467,17 +2544,17 @@
       }
     },
     "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
-      "version": "5.57.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.1.tgz",
-      "integrity": "sha512-RjQrAniDU0CEk5r7iphkm731zKlFiUjvcBS2yHAg8WWqFMCaCrD0rKEVOMUyMMcbGPZ0bPp56srkGWrgfZqLRA==",
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz",
+      "integrity": "sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==",
       "dev": true,
       "peer": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.57.1",
-        "eslint-visitor-keys": "^3.3.0"
+        "@typescript-eslint/types": "6.3.0",
+        "eslint-visitor-keys": "^3.4.1"
       },
       "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+        "node": "^16.0.0 || >=18.0.0"
       },
       "funding": {
         "type": "opencollective",
@@ -2485,13 +2562,13 @@
       }
     },
     "node_modules/@typescript-eslint/scope-manager": {
-      "version": "5.59.9",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.9.tgz",
-      "integrity": "sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ==",
+      "version": "5.60.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.60.1.tgz",
+      "integrity": "sha512-Dn/LnN7fEoRD+KspEOV0xDMynEmR3iSHdgNsarlXNLGGtcUok8L4N71dxUgt3YvlO8si7E+BJ5Fe3wb5yUw7DQ==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.59.9",
-        "@typescript-eslint/visitor-keys": "5.59.9"
+        "@typescript-eslint/types": "5.60.1",
+        "@typescript-eslint/visitor-keys": "5.60.1"
       },
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -2502,9 +2579,9 @@
       }
     },
     "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/types": {
-      "version": "5.59.9",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.9.tgz",
-      "integrity": "sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==",
+      "version": "5.60.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.1.tgz",
+      "integrity": "sha512-zDcDx5fccU8BA0IDZc71bAtYIcG9PowaOwaD8rjYbqwK7dpe/UMQl3inJ4UtUK42nOCT41jTSCwg76E62JpMcg==",
       "dev": true,
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -2515,25 +2592,25 @@
       }
     },
     "node_modules/@typescript-eslint/type-utils": {
-      "version": "5.59.9",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.9.tgz",
-      "integrity": "sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q==",
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.3.0.tgz",
+      "integrity": "sha512-7Oj+1ox1T2Yc8PKpBvOKWhoI/4rWFd1j7FA/rPE0lbBPXTKjdbtC+7Ev0SeBjEKkIhKWVeZSP+mR7y1Db1CdfQ==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/typescript-estree": "5.59.9",
-        "@typescript-eslint/utils": "5.59.9",
+        "@typescript-eslint/typescript-estree": "6.3.0",
+        "@typescript-eslint/utils": "6.3.0",
         "debug": "^4.3.4",
-        "tsutils": "^3.21.0"
+        "ts-api-utils": "^1.0.1"
       },
       "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+        "node": "^16.0.0 || >=18.0.0"
       },
       "funding": {
         "type": "opencollective",
         "url": "https://opencollective.com/typescript-eslint"
       },
       "peerDependencies": {
-        "eslint": "*"
+        "eslint": "^7.0.0 || ^8.0.0"
       },
       "peerDependenciesMeta": {
         "typescript": {
@@ -2541,54 +2618,72 @@
         }
       }
     },
-    "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": {
-      "version": "5.59.9",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.9.tgz",
-      "integrity": "sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==",
+    "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": {
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.3.0.tgz",
+      "integrity": "sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==",
       "dev": true,
+      "dependencies": {
+        "@typescript-eslint/types": "6.3.0",
+        "@typescript-eslint/visitor-keys": "6.3.0"
+      },
       "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+        "node": "^16.0.0 || >=18.0.0"
       },
       "funding": {
         "type": "opencollective",
         "url": "https://opencollective.com/typescript-eslint"
       }
     },
-    "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": {
-      "version": "5.59.9",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz",
-      "integrity": "sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA==",
+    "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": {
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.3.0.tgz",
+      "integrity": "sha512-hLLg3BZE07XHnpzglNBG8P/IXq/ZVXraEbgY7FM0Cnc1ehM8RMdn9mat3LubJ3KBeYXXPxV1nugWbQPjGeJk6Q==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.59.9",
-        "@typescript-eslint/visitor-keys": "5.59.9",
-        "debug": "^4.3.4",
-        "globby": "^11.1.0",
-        "is-glob": "^4.0.3",
-        "semver": "^7.3.7",
-        "tsutils": "^3.21.0"
+        "@eslint-community/eslint-utils": "^4.4.0",
+        "@types/json-schema": "^7.0.12",
+        "@types/semver": "^7.5.0",
+        "@typescript-eslint/scope-manager": "6.3.0",
+        "@typescript-eslint/types": "6.3.0",
+        "@typescript-eslint/typescript-estree": "6.3.0",
+        "semver": "^7.5.4"
       },
       "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+        "node": "^16.0.0 || >=18.0.0"
       },
       "funding": {
         "type": "opencollective",
         "url": "https://opencollective.com/typescript-eslint"
       },
-      "peerDependenciesMeta": {
-        "typescript": {
-          "optional": true
-        }
+      "peerDependencies": {
+        "eslint": "^7.0.0 || ^8.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": {
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz",
+      "integrity": "sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==",
+      "dev": true,
+      "dependencies": {
+        "@typescript-eslint/types": "6.3.0",
+        "eslint-visitor-keys": "^3.4.1"
+      },
+      "engines": {
+        "node": "^16.0.0 || >=18.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
       }
     },
     "node_modules/@typescript-eslint/types": {
-      "version": "5.57.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.57.1.tgz",
-      "integrity": "sha512-bSs4LOgyV3bJ08F5RDqO2KXqg3WAdwHCu06zOqcQ6vqbTJizyBhuh1o1ImC69X4bV2g1OJxbH71PJqiO7Y1RuA==",
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.3.0.tgz",
+      "integrity": "sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==",
       "dev": true,
-      "peer": true,
       "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+        "node": "^16.0.0 || >=18.0.0"
       },
       "funding": {
         "type": "opencollective",
@@ -2596,22 +2691,21 @@
       }
     },
     "node_modules/@typescript-eslint/typescript-estree": {
-      "version": "5.57.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.57.1.tgz",
-      "integrity": "sha512-A2MZqD8gNT0qHKbk2wRspg7cHbCDCk2tcqt6ScCFLr5Ru8cn+TCfM786DjPhqwseiS+PrYwcXht5ztpEQ6TFTw==",
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.3.0.tgz",
+      "integrity": "sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==",
       "dev": true,
-      "peer": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.57.1",
-        "@typescript-eslint/visitor-keys": "5.57.1",
+        "@typescript-eslint/types": "6.3.0",
+        "@typescript-eslint/visitor-keys": "6.3.0",
         "debug": "^4.3.4",
         "globby": "^11.1.0",
         "is-glob": "^4.0.3",
-        "semver": "^7.3.7",
-        "tsutils": "^3.21.0"
+        "semver": "^7.5.4",
+        "ts-api-utils": "^1.0.1"
       },
       "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+        "node": "^16.0.0 || >=18.0.0"
       },
       "funding": {
         "type": "opencollective",
@@ -2624,17 +2718,16 @@
       }
     },
     "node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/visitor-keys": {
-      "version": "5.57.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.1.tgz",
-      "integrity": "sha512-RjQrAniDU0CEk5r7iphkm731zKlFiUjvcBS2yHAg8WWqFMCaCrD0rKEVOMUyMMcbGPZ0bPp56srkGWrgfZqLRA==",
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz",
+      "integrity": "sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==",
       "dev": true,
-      "peer": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.57.1",
-        "eslint-visitor-keys": "^3.3.0"
+        "@typescript-eslint/types": "6.3.0",
+        "eslint-visitor-keys": "^3.4.1"
       },
       "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+        "node": "^16.0.0 || >=18.0.0"
       },
       "funding": {
         "type": "opencollective",
@@ -2642,17 +2735,17 @@
       }
     },
     "node_modules/@typescript-eslint/utils": {
-      "version": "5.59.9",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.9.tgz",
-      "integrity": "sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg==",
+      "version": "5.60.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.60.1.tgz",
+      "integrity": "sha512-tiJ7FFdFQOWssFa3gqb94Ilexyw0JVxj6vBzaSpfN/8IhoKkDuSAenUKvsSHw2A/TMpJb26izIszTXaqygkvpQ==",
       "dev": true,
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.2.0",
         "@types/json-schema": "^7.0.9",
         "@types/semver": "^7.3.12",
-        "@typescript-eslint/scope-manager": "5.59.9",
-        "@typescript-eslint/types": "5.59.9",
-        "@typescript-eslint/typescript-estree": "5.59.9",
+        "@typescript-eslint/scope-manager": "5.60.1",
+        "@typescript-eslint/types": "5.60.1",
+        "@typescript-eslint/typescript-estree": "5.60.1",
         "eslint-scope": "^5.1.1",
         "semver": "^7.3.7"
       },
@@ -2668,9 +2761,9 @@
       }
     },
     "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": {
-      "version": "5.59.9",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.9.tgz",
-      "integrity": "sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==",
+      "version": "5.60.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.1.tgz",
+      "integrity": "sha512-zDcDx5fccU8BA0IDZc71bAtYIcG9PowaOwaD8rjYbqwK7dpe/UMQl3inJ4UtUK42nOCT41jTSCwg76E62JpMcg==",
       "dev": true,
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -2681,13 +2774,13 @@
       }
     },
     "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": {
-      "version": "5.59.9",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz",
-      "integrity": "sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA==",
+      "version": "5.60.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.1.tgz",
+      "integrity": "sha512-hkX70J9+2M2ZT6fhti5Q2FoU9zb+GeZK2SLP1WZlvUDqdMbEKhexZODD1WodNRyO8eS+4nScvT0dts8IdaBzfw==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.59.9",
-        "@typescript-eslint/visitor-keys": "5.59.9",
+        "@typescript-eslint/types": "5.60.1",
+        "@typescript-eslint/visitor-keys": "5.60.1",
         "debug": "^4.3.4",
         "globby": "^11.1.0",
         "is-glob": "^4.0.3",
@@ -2708,12 +2801,12 @@
       }
     },
     "node_modules/@typescript-eslint/visitor-keys": {
-      "version": "5.59.9",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.9.tgz",
-      "integrity": "sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q==",
+      "version": "5.60.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.1.tgz",
+      "integrity": "sha512-xEYIxKcultP6E/RMKqube11pGjXH1DCo60mQoWhVYyKfLkwbIVVjYxmOenNMxILx0TjCujPTjjnTIVzm09TXIw==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.59.9",
+        "@typescript-eslint/types": "5.60.1",
         "eslint-visitor-keys": "^3.3.0"
       },
       "engines": {
@@ -2725,9 +2818,9 @@
       }
     },
     "node_modules/@typescript-eslint/visitor-keys/node_modules/@typescript-eslint/types": {
-      "version": "5.59.9",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.9.tgz",
-      "integrity": "sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==",
+      "version": "5.60.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.1.tgz",
+      "integrity": "sha512-zDcDx5fccU8BA0IDZc71bAtYIcG9PowaOwaD8rjYbqwK7dpe/UMQl3inJ4UtUK42nOCT41jTSCwg76E62JpMcg==",
       "dev": true,
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -2738,13 +2831,13 @@
       }
     },
     "node_modules/@vitest/expect": {
-      "version": "0.32.0",
-      "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.32.0.tgz",
-      "integrity": "sha512-VxVHhIxKw9Lux+O9bwLEEk2gzOUe93xuFHy9SzYWnnoYZFYg1NfBtnfnYWiJN7yooJ7KNElCK5YtA7DTZvtXtg==",
+      "version": "0.34.1",
+      "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.1.tgz",
+      "integrity": "sha512-q2CD8+XIsQ+tHwypnoCk8Mnv5e6afLFvinVGCq3/BOT4kQdVQmY6rRfyKkwcg635lbliLPqbunXZr+L1ssUWiQ==",
       "dev": true,
       "dependencies": {
-        "@vitest/spy": "0.32.0",
-        "@vitest/utils": "0.32.0",
+        "@vitest/spy": "0.34.1",
+        "@vitest/utils": "0.34.1",
         "chai": "^4.3.7"
       },
       "funding": {
@@ -2752,15 +2845,14 @@
       }
     },
     "node_modules/@vitest/runner": {
-      "version": "0.32.0",
-      "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.32.0.tgz",
-      "integrity": "sha512-QpCmRxftHkr72xt5A08xTEs9I4iWEXIOCHWhQQguWOKE4QH7DXSKZSOFibuwEIMAD7G0ERvtUyQn7iPWIqSwmw==",
+      "version": "0.34.1",
+      "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.1.tgz",
+      "integrity": "sha512-YfQMpYzDsYB7yqgmlxZ06NI4LurHWfrH7Wy3Pvf/z/vwUSgq1zLAb1lWcItCzQG+NVox+VvzlKQrYEXb47645g==",
       "dev": true,
       "dependencies": {
-        "@vitest/utils": "0.32.0",
-        "concordance": "^5.0.4",
+        "@vitest/utils": "0.34.1",
         "p-limit": "^4.0.0",
-        "pathe": "^1.1.0"
+        "pathe": "^1.1.1"
       },
       "funding": {
         "url": "https://opencollective.com/vitest"
@@ -2794,40 +2886,40 @@
       }
     },
     "node_modules/@vitest/snapshot": {
-      "version": "0.32.0",
-      "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.32.0.tgz",
-      "integrity": "sha512-yCKorPWjEnzpUxQpGlxulujTcSPgkblwGzAUEL+z01FTUg/YuCDZ8dxr9sHA08oO2EwxzHXNLjQKWJ2zc2a19Q==",
+      "version": "0.34.1",
+      "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.1.tgz",
+      "integrity": "sha512-0O9LfLU0114OqdF8lENlrLsnn024Tb1CsS9UwG0YMWY2oGTQfPtkW+B/7ieyv0X9R2Oijhi3caB1xgGgEgclSQ==",
       "dev": true,
       "dependencies": {
-        "magic-string": "^0.30.0",
-        "pathe": "^1.1.0",
-        "pretty-format": "^27.5.1"
+        "magic-string": "^0.30.1",
+        "pathe": "^1.1.1",
+        "pretty-format": "^29.5.0"
       },
       "funding": {
         "url": "https://opencollective.com/vitest"
       }
     },
     "node_modules/@vitest/spy": {
-      "version": "0.32.0",
-      "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.32.0.tgz",
-      "integrity": "sha512-MruAPlM0uyiq3d53BkwTeShXY0rYEfhNGQzVO5GHBmmX3clsxcWp79mMnkOVcV244sNTeDcHbcPFWIjOI4tZvw==",
+      "version": "0.34.1",
+      "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.1.tgz",
+      "integrity": "sha512-UT4WcI3EAPUNO8n6y9QoEqynGGEPmmRxC+cLzneFFXpmacivjHZsNbiKD88KUScv5DCHVDgdBsLD7O7s1enFcQ==",
       "dev": true,
       "dependencies": {
-        "tinyspy": "^2.1.0"
+        "tinyspy": "^2.1.1"
       },
       "funding": {
         "url": "https://opencollective.com/vitest"
       }
     },
     "node_modules/@vitest/utils": {
-      "version": "0.32.0",
-      "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.32.0.tgz",
-      "integrity": "sha512-53yXunzx47MmbuvcOPpLaVljHaeSu1G2dHdmy7+9ngMnQIkBQcvwOcoclWFnxDMxFbnq8exAfh3aKSZaK71J5A==",
+      "version": "0.34.1",
+      "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.1.tgz",
+      "integrity": "sha512-/ql9dsFi4iuEbiNcjNHQWXBum7aL8pyhxvfnD9gNtbjR9fUKAjxhj4AA3yfLXg6gJpMGGecvtF8Au2G9y3q47Q==",
       "dev": true,
       "dependencies": {
-        "concordance": "^5.0.4",
+        "diff-sequences": "^29.4.3",
         "loupe": "^2.3.6",
-        "pretty-format": "^27.5.1"
+        "pretty-format": "^29.5.0"
       },
       "funding": {
         "url": "https://opencollective.com/vitest"
@@ -2851,9 +2943,9 @@
       }
     },
     "node_modules/acorn": {
-      "version": "8.8.2",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
-      "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
+      "version": "8.9.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz",
+      "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==",
       "dev": true,
       "bin": {
         "acorn": "bin/acorn"
@@ -3243,9 +3335,9 @@
       }
     },
     "node_modules/babel-plugin-jsx-dom-expressions": {
-      "version": "0.36.7",
-      "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.36.7.tgz",
-      "integrity": "sha512-SqrwOKvAO3jM8CJ+FdPsldSFS1smPJvI1VyjsQQRU4VWjvIUgNFL8e1Ze0Z8IgsuNEbsRLUu/y3PDOQBFsarwA==",
+      "version": "0.36.10",
+      "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.36.10.tgz",
+      "integrity": "sha512-QA2k/14WGw+RgcGGnEuLWwnu4em6CGhjeXtjvgOYyFHYS2a+CzPeaVQHDOlfuiBcjq/3hWMspHMIMnPEOIzdBg==",
       "dev": true,
       "dependencies": {
         "@babel/helper-module-imports": "7.18.6",
@@ -3271,12 +3363,12 @@
       }
     },
     "node_modules/babel-preset-solid": {
-      "version": "1.7.2",
-      "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.7.2.tgz",
-      "integrity": "sha512-2SVcLTk6RXgXv3ebbm4iKiAPTPhQ/+3zd1KUOnMq/qBMr9ZshzdtIS4dMr9orWPHwDTdvJ2ZAadyGf3ZfTwWjg==",
+      "version": "1.7.7",
+      "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.7.7.tgz",
+      "integrity": "sha512-tdxVzx3kgcIjNXAOmGRbzIhFBPeJjSakiN9yM+IYdL/+LtXNnbGqb0Va5tJb8Sjbk+QVEriovCyuzB5T7jeTvg==",
       "dev": true,
       "dependencies": {
-        "babel-plugin-jsx-dom-expressions": "^0.36.7"
+        "babel-plugin-jsx-dom-expressions": "^0.36.10"
       },
       "peerDependencies": {
         "@babel/core": "^7.0.0"
@@ -3374,9 +3466,9 @@
       }
     },
     "node_modules/bin-version-check/node_modules/semver": {
-      "version": "5.7.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+      "version": "5.7.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
       "dev": true,
       "bin": {
         "semver": "bin/semver"
@@ -3438,9 +3530,9 @@
       }
     },
     "node_modules/bin-version/node_modules/semver": {
-      "version": "5.7.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+      "version": "5.7.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
       "dev": true,
       "bin": {
         "semver": "bin/semver"
@@ -4122,25 +4214,6 @@
         "typedarray": "^0.0.6"
       }
     },
-    "node_modules/concordance": {
-      "version": "5.0.4",
-      "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.4.tgz",
-      "integrity": "sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==",
-      "dev": true,
-      "dependencies": {
-        "date-time": "^3.1.0",
-        "esutils": "^2.0.3",
-        "fast-diff": "^1.2.0",
-        "js-string-escape": "^1.0.1",
-        "lodash": "^4.17.15",
-        "md5-hex": "^3.0.1",
-        "semver": "^7.3.2",
-        "well-known-symbols": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=10.18.0 <11 || >=12.14.0 <13 || >=14"
-      }
-    },
     "node_modules/config-chain": {
       "version": "1.1.13",
       "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
@@ -4290,18 +4363,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/date-time": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/date-time/-/date-time-3.1.0.tgz",
-      "integrity": "sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==",
-      "dev": true,
-      "dependencies": {
-        "time-zone": "^1.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
     "node_modules/debug": {
       "version": "4.3.4",
       "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -4645,6 +4706,15 @@
         "node": ">=0.3.1"
       }
     },
+    "node_modules/diff-sequences": {
+      "version": "29.4.3",
+      "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz",
+      "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==",
+      "dev": true,
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
     "node_modules/dir-glob": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -4882,10 +4952,9 @@
       }
     },
     "node_modules/esbuild": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.0.tgz",
-      "integrity": "sha512-/2sQaWHNX2jkglLu85EjmEAR2ANpKOa1kp2rAE3wjKcuYjEHFlB+D60tn6W9BRgHiAQEKYtl4hEygKWothfDEA==",
-      "dev": true,
+      "version": "0.18.17",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.17.tgz",
+      "integrity": "sha512-1GJtYnUxsJreHYA0Y+iQz2UEykonY66HNWOb0yXYZi9/kNrORUEHVg87eQsCtqh59PEJ5YVZJO98JHznMJSWjg==",
       "hasInstallScript": true,
       "bin": {
         "esbuild": "bin/esbuild"
@@ -4894,28 +4963,28 @@
         "node": ">=12"
       },
       "optionalDependencies": {
-        "@esbuild/android-arm": "0.18.0",
-        "@esbuild/android-arm64": "0.18.0",
-        "@esbuild/android-x64": "0.18.0",
-        "@esbuild/darwin-arm64": "0.18.0",
-        "@esbuild/darwin-x64": "0.18.0",
-        "@esbuild/freebsd-arm64": "0.18.0",
-        "@esbuild/freebsd-x64": "0.18.0",
-        "@esbuild/linux-arm": "0.18.0",
-        "@esbuild/linux-arm64": "0.18.0",
-        "@esbuild/linux-ia32": "0.18.0",
-        "@esbuild/linux-loong64": "0.18.0",
-        "@esbuild/linux-mips64el": "0.18.0",
-        "@esbuild/linux-ppc64": "0.18.0",
-        "@esbuild/linux-riscv64": "0.18.0",
-        "@esbuild/linux-s390x": "0.18.0",
-        "@esbuild/linux-x64": "0.18.0",
-        "@esbuild/netbsd-x64": "0.18.0",
-        "@esbuild/openbsd-x64": "0.18.0",
-        "@esbuild/sunos-x64": "0.18.0",
-        "@esbuild/win32-arm64": "0.18.0",
-        "@esbuild/win32-ia32": "0.18.0",
-        "@esbuild/win32-x64": "0.18.0"
+        "@esbuild/android-arm": "0.18.17",
+        "@esbuild/android-arm64": "0.18.17",
+        "@esbuild/android-x64": "0.18.17",
+        "@esbuild/darwin-arm64": "0.18.17",
+        "@esbuild/darwin-x64": "0.18.17",
+        "@esbuild/freebsd-arm64": "0.18.17",
+        "@esbuild/freebsd-x64": "0.18.17",
+        "@esbuild/linux-arm": "0.18.17",
+        "@esbuild/linux-arm64": "0.18.17",
+        "@esbuild/linux-ia32": "0.18.17",
+        "@esbuild/linux-loong64": "0.18.17",
+        "@esbuild/linux-mips64el": "0.18.17",
+        "@esbuild/linux-ppc64": "0.18.17",
+        "@esbuild/linux-riscv64": "0.18.17",
+        "@esbuild/linux-s390x": "0.18.17",
+        "@esbuild/linux-x64": "0.18.17",
+        "@esbuild/netbsd-x64": "0.18.17",
+        "@esbuild/openbsd-x64": "0.18.17",
+        "@esbuild/sunos-x64": "0.18.17",
+        "@esbuild/win32-arm64": "0.18.17",
+        "@esbuild/win32-ia32": "0.18.17",
+        "@esbuild/win32-x64": "0.18.17"
       }
     },
     "node_modules/escalade": {
@@ -4939,27 +5008,27 @@
       }
     },
     "node_modules/eslint": {
-      "version": "8.42.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz",
-      "integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==",
+      "version": "8.46.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.46.0.tgz",
+      "integrity": "sha512-cIO74PvbW0qU8e0mIvk5IV3ToWdCq5FYG6gWPHHkx6gNdjlbAYvtfHmlCMXxjcoVaIdwy/IAt3+mDkZkfvb2Dg==",
       "dev": true,
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.2.0",
-        "@eslint-community/regexpp": "^4.4.0",
-        "@eslint/eslintrc": "^2.0.3",
-        "@eslint/js": "8.42.0",
+        "@eslint-community/regexpp": "^4.6.1",
+        "@eslint/eslintrc": "^2.1.1",
+        "@eslint/js": "^8.46.0",
         "@humanwhocodes/config-array": "^0.11.10",
         "@humanwhocodes/module-importer": "^1.0.1",
         "@nodelib/fs.walk": "^1.2.8",
-        "ajv": "^6.10.0",
+        "ajv": "^6.12.4",
         "chalk": "^4.0.0",
         "cross-spawn": "^7.0.2",
         "debug": "^4.3.2",
         "doctrine": "^3.0.0",
         "escape-string-regexp": "^4.0.0",
-        "eslint-scope": "^7.2.0",
-        "eslint-visitor-keys": "^3.4.1",
-        "espree": "^9.5.2",
+        "eslint-scope": "^7.2.2",
+        "eslint-visitor-keys": "^3.4.2",
+        "espree": "^9.6.1",
         "esquery": "^1.4.2",
         "esutils": "^2.0.2",
         "fast-deep-equal": "^3.1.3",
@@ -4969,7 +5038,6 @@
         "globals": "^13.19.0",
         "graphemer": "^1.4.0",
         "ignore": "^5.2.0",
-        "import-fresh": "^3.0.0",
         "imurmurhash": "^0.1.4",
         "is-glob": "^4.0.0",
         "is-path-inside": "^3.0.3",
@@ -4979,9 +5047,8 @@
         "lodash.merge": "^4.6.2",
         "minimatch": "^3.1.2",
         "natural-compare": "^1.4.0",
-        "optionator": "^0.9.1",
+        "optionator": "^0.9.3",
         "strip-ansi": "^6.0.1",
-        "strip-json-comments": "^3.1.0",
         "text-table": "^0.2.0"
       },
       "bin": {
@@ -5034,9 +5101,9 @@
       }
     },
     "node_modules/eslint-plugin-react": {
-      "version": "7.32.2",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz",
-      "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==",
+      "version": "7.33.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.1.tgz",
+      "integrity": "sha512-L093k0WAMvr6VhNwReB8VgOq5s2LesZmrpPdKz/kZElQDzqS7G7+DnKoqT+w4JwuiGeAhAvHO0fvy0Eyk4ejDA==",
       "dev": true,
       "dependencies": {
         "array-includes": "^3.1.6",
@@ -5052,7 +5119,7 @@
         "object.values": "^1.1.6",
         "prop-types": "^15.8.1",
         "resolve": "^2.0.0-next.4",
-        "semver": "^6.3.0",
+        "semver": "^6.3.1",
         "string.prototype.matchall": "^4.0.8"
       },
       "engines": {
@@ -5075,9 +5142,9 @@
       }
     },
     "node_modules/eslint-plugin-react/node_modules/semver": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-      "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
       "dev": true,
       "bin": {
         "semver": "bin/semver.js"
@@ -5158,9 +5225,9 @@
       }
     },
     "node_modules/eslint-visitor-keys": {
-      "version": "3.4.1",
-      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz",
-      "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==",
+      "version": "3.4.2",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz",
+      "integrity": "sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==",
       "dev": true,
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -5170,9 +5237,9 @@
       }
     },
     "node_modules/eslint/node_modules/eslint-scope": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz",
-      "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==",
+      "version": "7.2.2",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+      "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
       "dev": true,
       "dependencies": {
         "esrecurse": "^4.3.0",
@@ -5198,12 +5265,12 @@
       }
     },
     "node_modules/espree": {
-      "version": "9.5.2",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz",
-      "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==",
+      "version": "9.6.1",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+      "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
       "dev": true,
       "dependencies": {
-        "acorn": "^8.8.0",
+        "acorn": "^8.9.0",
         "acorn-jsx": "^5.3.2",
         "eslint-visitor-keys": "^3.4.1"
       },
@@ -5449,12 +5516,6 @@
       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
     },
-    "node_modules/fast-diff": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
-      "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
-      "dev": true
-    },
     "node_modules/fast-glob": {
       "version": "3.2.12",
       "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
@@ -5936,16 +5997,16 @@
       }
     },
     "node_modules/glob": {
-      "version": "10.2.7",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.7.tgz",
-      "integrity": "sha512-jTKehsravOJo8IJxUGfZILnkvVJM/MOfHRs8QcXolVef2zNI9Tqyy5+SeuOAZd3upViEZQLyFpQhYiHLrMUNmA==",
+      "version": "10.3.3",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz",
+      "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==",
       "dev": true,
       "dependencies": {
         "foreground-child": "^3.1.0",
         "jackspeak": "^2.0.3",
         "minimatch": "^9.0.1",
-        "minipass": "^5.0.0 || ^6.0.2",
-        "path-scurry": "^1.7.0"
+        "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
+        "path-scurry": "^1.10.1"
       },
       "bin": {
         "glob": "dist/cjs/src/bin.js"
@@ -6147,12 +6208,6 @@
       "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
       "dev": true
     },
-    "node_modules/grapheme-splitter": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
-      "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
-      "dev": true
-    },
     "node_modules/graphemer": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
@@ -7168,15 +7223,6 @@
         "node": ">=10"
       }
     },
-    "node_modules/js-string-escape": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz",
-      "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
     "node_modules/js-tokens": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -7625,17 +7671,23 @@
       }
     },
     "node_modules/magic-string": {
-      "version": "0.30.0",
-      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz",
-      "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==",
+      "version": "0.30.1",
+      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.1.tgz",
+      "integrity": "sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==",
       "dev": true,
       "dependencies": {
-        "@jridgewell/sourcemap-codec": "^1.4.13"
+        "@jridgewell/sourcemap-codec": "^1.4.15"
       },
       "engines": {
         "node": ">=12"
       }
     },
+    "node_modules/magic-string/node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.4.15",
+      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+      "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
+      "dev": true
+    },
     "node_modules/make-dir": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
@@ -7665,18 +7717,6 @@
         "url": "https://github.com/sponsors/wooorm"
       }
     },
-    "node_modules/md5-hex": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz",
-      "integrity": "sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==",
-      "dev": true,
-      "dependencies": {
-        "blueimp-md5": "^2.10.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/mdast-comment-marker": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/mdast-comment-marker/-/mdast-comment-marker-2.1.2.tgz",
@@ -8411,13 +8451,13 @@
       }
     },
     "node_modules/mlly": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.3.0.tgz",
-      "integrity": "sha512-HT5mcgIQKkOrZecOjOX3DJorTikWXwsBfpcr/MGBkhfWcjiqvnaL/9ppxvIUXfjT6xt4DVIAsN9fMUz1ev4bIw==",
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.0.tgz",
+      "integrity": "sha512-ua8PAThnTwpprIaU47EPeZ/bPUVp2QYBbWMphUQpVdBI3Lgqzm5KZQ45Agm3YJedHXaIHl6pBGabaLSUPPSptg==",
       "dev": true,
       "dependencies": {
-        "acorn": "^8.8.2",
-        "pathe": "^1.1.0",
+        "acorn": "^8.9.0",
+        "pathe": "^1.1.1",
         "pkg-types": "^1.0.3",
         "ufo": "^1.1.2"
       }
@@ -8547,9 +8587,9 @@
       }
     },
     "node_modules/normalize-package-data/node_modules/semver": {
-      "version": "5.7.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+      "version": "5.7.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
       "dev": true,
       "bin": {
         "semver": "bin/semver"
@@ -8815,17 +8855,17 @@
       }
     },
     "node_modules/optionator": {
-      "version": "0.9.1",
-      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
-      "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+      "version": "0.9.3",
+      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
+      "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
       "dev": true,
       "dependencies": {
+        "@aashutoshrathi/word-wrap": "^1.2.3",
         "deep-is": "^0.1.3",
         "fast-levenshtein": "^2.0.6",
         "levn": "^0.4.1",
         "prelude-ls": "^1.2.1",
-        "type-check": "^0.4.0",
-        "word-wrap": "^1.2.3"
+        "type-check": "^0.4.0"
       },
       "engines": {
         "node": ">= 0.8.0"
@@ -9072,13 +9112,13 @@
       "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
     },
     "node_modules/path-scurry": {
-      "version": "1.7.0",
-      "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.7.0.tgz",
-      "integrity": "sha512-UkZUeDjczjYRE495+9thsgcVgsaCPkaw80slmfVFgllxY+IO8ubTsOpFVjDPROBqJdHfVPUFRHPBV/WciOVfWg==",
+      "version": "1.10.1",
+      "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
+      "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
       "dev": true,
       "dependencies": {
-        "lru-cache": "^9.0.0",
-        "minipass": "^5.0.0"
+        "lru-cache": "^9.1.1 || ^10.0.0",
+        "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
       },
       "engines": {
         "node": ">=16 || 14 >=14.17"
@@ -9088,9 +9128,9 @@
       }
     },
     "node_modules/path-scurry/node_modules/lru-cache": {
-      "version": "9.1.0",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.0.tgz",
-      "integrity": "sha512-qFXQEwchrZcMVen2uIDceR8Tii6kCJak5rzDStfEM0qA3YLMswaxIEZO0DhIbJ3aqaJiDjt+3crlplOb0tDtKQ==",
+      "version": "10.0.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.0.tgz",
+      "integrity": "sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==",
       "dev": true,
       "engines": {
         "node": "14 || >=16.14"
@@ -9430,15 +9470,15 @@
       }
     },
     "node_modules/prettier": {
-      "version": "2.8.8",
-      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
-      "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.1.tgz",
+      "integrity": "sha512-fcOWSnnpCrovBsmFZIGIy9UqK2FaI7Hqax+DIO0A9UxeVoY4iweyaFjS5TavZN97Hfehph0nhsZnjlVKzEQSrQ==",
       "dev": true,
       "bin": {
-        "prettier": "bin-prettier.js"
+        "prettier": "bin/prettier.cjs"
       },
       "engines": {
-        "node": ">=10.13.0"
+        "node": ">=14"
       },
       "funding": {
         "url": "https://github.com/prettier/prettier?sponsor=1"
@@ -9457,17 +9497,17 @@
       }
     },
     "node_modules/pretty-format": {
-      "version": "27.5.1",
-      "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
-      "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
+      "version": "29.6.2",
+      "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.2.tgz",
+      "integrity": "sha512-1q0oC8eRveTg5nnBEWMXAU2qpv65Gnuf2eCQzSjxpWFkPaPARwqZZDGuNE0zPAZfTCHzIk3A8dIjwlQKKLphyg==",
       "dev": true,
       "dependencies": {
-        "ansi-regex": "^5.0.1",
+        "@jest/schemas": "^29.6.0",
         "ansi-styles": "^5.0.0",
-        "react-is": "^17.0.1"
+        "react-is": "^18.0.0"
       },
       "engines": {
-        "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
       }
     },
     "node_modules/pretty-format/node_modules/ansi-styles": {
@@ -9483,9 +9523,9 @@
       }
     },
     "node_modules/pretty-format/node_modules/react-is": {
-      "version": "17.0.2",
-      "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
-      "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
+      "version": "18.2.0",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+      "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
       "dev": true
     },
     "node_modules/proc-log": {
@@ -10280,9 +10320,9 @@
       }
     },
     "node_modules/rollup": {
-      "version": "3.21.1",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.21.1.tgz",
-      "integrity": "sha512-GpUgqWCw56OSiBKf7lcAITstYiBV1/EKaKYPl9r8HgAxc6/qYAVw1PaHWnvHWFziRaf4HsVCDLq/IGtBi1K/Zw==",
+      "version": "3.26.2",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.2.tgz",
+      "integrity": "sha512-6umBIGVz93er97pMgQO08LuH3m6PUb3jlDUUGFsNJB6VgTCUaDFpupf5JfU30529m/UKOgmiX+uY6Sx8cOYpLA==",
       "bin": {
         "rollup": "dist/bin/rollup"
       },
@@ -10362,9 +10402,9 @@
       }
     },
     "node_modules/sass": {
-      "version": "1.63.3",
-      "resolved": "https://registry.npmjs.org/sass/-/sass-1.63.3.tgz",
-      "integrity": "sha512-ySdXN+DVpfwq49jG1+hmtDslYqpS7SkOR5GpF6o2bmb1RL/xS+wvPmegMvMywyfsmAV6p7TgwXYGrCZIFFbAHg==",
+      "version": "1.64.2",
+      "resolved": "https://registry.npmjs.org/sass/-/sass-1.64.2.tgz",
+      "integrity": "sha512-TnDlfc+CRnUAgLO9D8cQLFu/GIjJIzJCGkE7o4ekIGQOH7T3GetiRR/PsTWJUHhkzcSPrARkPI+gNWn5alCzDg==",
       "devOptional": true,
       "dependencies": {
         "chokidar": ">=3.0.0 <4.0.0",
@@ -10392,9 +10432,9 @@
       }
     },
     "node_modules/semver": {
-      "version": "7.3.8",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
-      "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+      "version": "7.5.4",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+      "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
       "dependencies": {
         "lru-cache": "^6.0.0"
       },
@@ -10427,9 +10467,9 @@
       }
     },
     "node_modules/semver-truncate/node_modules/semver": {
-      "version": "5.7.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+      "version": "5.7.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
       "dev": true,
       "bin": {
         "semver": "bin/semver"
@@ -10575,9 +10615,9 @@
       }
     },
     "node_modules/solid-js": {
-      "version": "1.7.6",
-      "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.7.6.tgz",
-      "integrity": "sha512-DXVOTjUh/bIAhE0fIqu3ezGLyQaez7v8EOw3uPLIi87DmLjg+hsuCAgKyNIZ+o4jUetOk3ZORccvJmE1yZUk8g==",
+      "version": "1.7.9",
+      "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.7.9.tgz",
+      "integrity": "sha512-p1orXnauMQmwYULZtuPAXyKNRGEN2qh60kLX4YURa3jvulxAqjlh2kWEljXCtAVR6UZPC16NXdj9ASHcH383Fg==",
       "dependencies": {
         "csstype": "^3.1.0",
         "seroval": "^0.5.0"
@@ -10768,9 +10808,9 @@
       "dev": true
     },
     "node_modules/std-env": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.3.2.tgz",
-      "integrity": "sha512-uUZI65yrV2Qva5gqE0+A7uVAvO40iPo6jGhs7s8keRfHCmtg+uB2X6EiLGCI9IgL1J17xGhvoOqSz79lzICPTA==",
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.3.3.tgz",
+      "integrity": "sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==",
       "dev": true
     },
     "node_modules/strict-uri-encode": {
@@ -11349,9 +11389,9 @@
       }
     },
     "node_modules/stylelint/node_modules/read-pkg/node_modules/semver": {
-      "version": "5.7.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+      "version": "5.7.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
       "bin": {
         "semver": "bin/semver"
       }
@@ -11567,15 +11607,6 @@
       "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
       "dev": true
     },
-    "node_modules/time-zone": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz",
-      "integrity": "sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
     "node_modules/timed-out": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
@@ -11592,9 +11623,9 @@
       "dev": true
     },
     "node_modules/tinypool": {
-      "version": "0.5.0",
-      "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.5.0.tgz",
-      "integrity": "sha512-paHQtnrlS1QZYKF/GnLoOM/DN9fqaGOFbCbxzAhwniySnzl9Ebk8w73/dd34DAhe/obUbPAOldTyYXQZxnPBPQ==",
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz",
+      "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==",
       "dev": true,
       "engines": {
         "node": ">=14.0.0"
@@ -11711,6 +11742,18 @@
         "url": "https://github.com/sponsors/wooorm"
       }
     },
+    "node_modules/ts-api-utils": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz",
+      "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==",
+      "dev": true,
+      "engines": {
+        "node": ">=16.13.0"
+      },
+      "peerDependencies": {
+        "typescript": ">=4.2.0"
+      }
+    },
     "node_modules/tslib": {
       "version": "1.14.1",
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
@@ -11823,9 +11866,9 @@
       }
     },
     "node_modules/typescript": {
-      "version": "5.1.3",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz",
-      "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==",
+      "version": "5.1.6",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
+      "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==",
       "dev": true,
       "bin": {
         "tsc": "bin/tsc",
@@ -11836,9 +11879,9 @@
       }
     },
     "node_modules/ufo": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.1.2.tgz",
-      "integrity": "sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.2.0.tgz",
+      "integrity": "sha512-RsPyTbqORDNDxqAdQPQBpgqhWle1VcTSou/FraClYlHf6TZnQcGslpLcAphNR+sQW4q5lLWLbOsRlh9j24baQg==",
       "dev": true
     },
     "node_modules/unbox-primitive": {
@@ -12056,9 +12099,9 @@
       }
     },
     "node_modules/unified-engine/node_modules/yaml": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz",
-      "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==",
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz",
+      "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==",
       "dev": true,
       "engines": {
         "node": ">= 14"
@@ -12527,13 +12570,13 @@
       }
     },
     "node_modules/vite": {
-      "version": "4.3.9",
-      "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz",
-      "integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==",
+      "version": "4.4.8",
+      "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.8.tgz",
+      "integrity": "sha512-LONawOUUjxQridNWGQlNizfKH89qPigK36XhMI7COMGztz8KNY0JHim7/xDd71CZwGT4HtSRgI7Hy+RlhG0Gvg==",
       "dependencies": {
-        "esbuild": "^0.17.5",
-        "postcss": "^8.4.23",
-        "rollup": "^3.21.0"
+        "esbuild": "^0.18.10",
+        "postcss": "^8.4.26",
+        "rollup": "^3.25.2"
       },
       "bin": {
         "vite": "bin/vite.js"
@@ -12541,12 +12584,16 @@
       "engines": {
         "node": "^14.18.0 || >=16.0.0"
       },
+      "funding": {
+        "url": "https://github.com/vitejs/vite?sponsor=1"
+      },
       "optionalDependencies": {
         "fsevents": "~2.3.2"
       },
       "peerDependencies": {
         "@types/node": ">= 14",
         "less": "*",
+        "lightningcss": "^1.21.0",
         "sass": "*",
         "stylus": "*",
         "sugarss": "*",
@@ -12559,6 +12606,9 @@
         "less": {
           "optional": true
         },
+        "lightningcss": {
+          "optional": true
+        },
         "sass": {
           "optional": true
         },
@@ -12574,15 +12624,15 @@
       }
     },
     "node_modules/vite-node": {
-      "version": "0.32.0",
-      "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.32.0.tgz",
-      "integrity": "sha512-220P/y8YacYAU+daOAqiGEFXx2A8AwjadDzQqos6wSukjvvTWNqleJSwoUn0ckyNdjHIKoxn93Nh1vWBqEKr3Q==",
+      "version": "0.34.1",
+      "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.1.tgz",
+      "integrity": "sha512-odAZAL9xFMuAg8aWd7nSPT+hU8u2r9gU3LRm9QKjxBEF2rRdWpMuqkrkjvyVQEdNFiBctqr2Gg4uJYizm5Le6w==",
       "dev": true,
       "dependencies": {
         "cac": "^6.7.14",
         "debug": "^4.3.4",
-        "mlly": "^1.2.0",
-        "pathe": "^1.1.0",
+        "mlly": "^1.4.0",
+        "pathe": "^1.1.1",
         "picocolors": "^1.0.0",
         "vite": "^3.0.0 || ^4.0.0"
       },
@@ -12631,9 +12681,9 @@
       }
     },
     "node_modules/vite-plugin-static-copy": {
-      "version": "0.16.0",
-      "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-0.16.0.tgz",
-      "integrity": "sha512-dMVEg5Z2SwYRgQnHZaeokvSKB4p/TOTf65JU4sP3U6ccSBsukqdtDOjpmT+xzTFHAA8WJjcS31RMLjUdWQCBzw==",
+      "version": "0.17.0",
+      "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-0.17.0.tgz",
+      "integrity": "sha512-2HpNbHfDt8SDy393AGXh9llHkc8FJMQkI8s3T5WsH3SWLMO+f5cFIyPErl4yGKU9Uh3Vaqsd4lHZYTf042fQ2A==",
       "dev": true,
       "dependencies": {
         "chokidar": "^3.5.3",
@@ -12654,381 +12704,15 @@
       "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
       "dev": true
     },
-    "node_modules/vite/node_modules/@esbuild/android-arm": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz",
-      "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==",
-      "cpu": [
-        "arm"
-      ],
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/android-arm64": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz",
-      "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==",
-      "cpu": [
-        "arm64"
-      ],
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/android-x64": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz",
-      "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==",
-      "cpu": [
-        "x64"
-      ],
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/darwin-arm64": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz",
-      "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==",
-      "cpu": [
-        "arm64"
-      ],
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/darwin-x64": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz",
-      "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==",
-      "cpu": [
-        "x64"
-      ],
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/freebsd-arm64": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz",
-      "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==",
-      "cpu": [
-        "arm64"
-      ],
-      "optional": true,
-      "os": [
-        "freebsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/freebsd-x64": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz",
-      "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==",
-      "cpu": [
-        "x64"
-      ],
-      "optional": true,
-      "os": [
-        "freebsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/linux-arm": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz",
-      "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==",
-      "cpu": [
-        "arm"
-      ],
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/linux-arm64": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz",
-      "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==",
-      "cpu": [
-        "arm64"
-      ],
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/linux-ia32": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz",
-      "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==",
-      "cpu": [
-        "ia32"
-      ],
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/linux-loong64": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz",
-      "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==",
-      "cpu": [
-        "loong64"
-      ],
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/linux-mips64el": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz",
-      "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==",
-      "cpu": [
-        "mips64el"
-      ],
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/linux-ppc64": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz",
-      "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==",
-      "cpu": [
-        "ppc64"
-      ],
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/linux-riscv64": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz",
-      "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==",
-      "cpu": [
-        "riscv64"
-      ],
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/linux-s390x": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz",
-      "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==",
-      "cpu": [
-        "s390x"
-      ],
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/linux-x64": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz",
-      "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==",
-      "cpu": [
-        "x64"
-      ],
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/netbsd-x64": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz",
-      "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==",
-      "cpu": [
-        "x64"
-      ],
-      "optional": true,
-      "os": [
-        "netbsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/openbsd-x64": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz",
-      "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==",
-      "cpu": [
-        "x64"
-      ],
-      "optional": true,
-      "os": [
-        "openbsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/sunos-x64": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz",
-      "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==",
-      "cpu": [
-        "x64"
-      ],
-      "optional": true,
-      "os": [
-        "sunos"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/win32-arm64": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz",
-      "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==",
-      "cpu": [
-        "arm64"
-      ],
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/win32-ia32": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz",
-      "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==",
-      "cpu": [
-        "ia32"
-      ],
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/@esbuild/win32-x64": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz",
-      "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==",
-      "cpu": [
-        "x64"
-      ],
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite/node_modules/esbuild": {
-      "version": "0.17.19",
-      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz",
-      "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==",
-      "hasInstallScript": true,
-      "bin": {
-        "esbuild": "bin/esbuild"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "optionalDependencies": {
-        "@esbuild/android-arm": "0.17.19",
-        "@esbuild/android-arm64": "0.17.19",
-        "@esbuild/android-x64": "0.17.19",
-        "@esbuild/darwin-arm64": "0.17.19",
-        "@esbuild/darwin-x64": "0.17.19",
-        "@esbuild/freebsd-arm64": "0.17.19",
-        "@esbuild/freebsd-x64": "0.17.19",
-        "@esbuild/linux-arm": "0.17.19",
-        "@esbuild/linux-arm64": "0.17.19",
-        "@esbuild/linux-ia32": "0.17.19",
-        "@esbuild/linux-loong64": "0.17.19",
-        "@esbuild/linux-mips64el": "0.17.19",
-        "@esbuild/linux-ppc64": "0.17.19",
-        "@esbuild/linux-riscv64": "0.17.19",
-        "@esbuild/linux-s390x": "0.17.19",
-        "@esbuild/linux-x64": "0.17.19",
-        "@esbuild/netbsd-x64": "0.17.19",
-        "@esbuild/openbsd-x64": "0.17.19",
-        "@esbuild/sunos-x64": "0.17.19",
-        "@esbuild/win32-arm64": "0.17.19",
-        "@esbuild/win32-ia32": "0.17.19",
-        "@esbuild/win32-x64": "0.17.19"
-      }
-    },
     "node_modules/vite/node_modules/picocolors": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
       "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
     },
     "node_modules/vite/node_modules/postcss": {
-      "version": "8.4.23",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz",
-      "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==",
+      "version": "8.4.27",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz",
+      "integrity": "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==",
       "funding": [
         {
           "type": "opencollective",
@@ -13067,35 +12751,34 @@
       }
     },
     "node_modules/vitest": {
-      "version": "0.32.0",
-      "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.32.0.tgz",
-      "integrity": "sha512-SW83o629gCqnV3BqBnTxhB10DAwzwEx3z+rqYZESehUB+eWsJxwcBQx7CKy0otuGMJTYh7qCVuUX23HkftGl/Q==",
+      "version": "0.34.1",
+      "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.1.tgz",
+      "integrity": "sha512-G1PzuBEq9A75XSU88yO5G4vPT20UovbC/2osB2KEuV/FisSIIsw7m5y2xMdB7RsAGHAfg2lPmp2qKr3KWliVlQ==",
       "dev": true,
       "dependencies": {
         "@types/chai": "^4.3.5",
         "@types/chai-subset": "^1.3.3",
         "@types/node": "*",
-        "@vitest/expect": "0.32.0",
-        "@vitest/runner": "0.32.0",
-        "@vitest/snapshot": "0.32.0",
-        "@vitest/spy": "0.32.0",
-        "@vitest/utils": "0.32.0",
-        "acorn": "^8.8.2",
+        "@vitest/expect": "0.34.1",
+        "@vitest/runner": "0.34.1",
+        "@vitest/snapshot": "0.34.1",
+        "@vitest/spy": "0.34.1",
+        "@vitest/utils": "0.34.1",
+        "acorn": "^8.9.0",
         "acorn-walk": "^8.2.0",
         "cac": "^6.7.14",
         "chai": "^4.3.7",
-        "concordance": "^5.0.4",
         "debug": "^4.3.4",
         "local-pkg": "^0.4.3",
-        "magic-string": "^0.30.0",
-        "pathe": "^1.1.0",
+        "magic-string": "^0.30.1",
+        "pathe": "^1.1.1",
         "picocolors": "^1.0.0",
-        "std-env": "^3.3.2",
+        "std-env": "^3.3.3",
         "strip-literal": "^1.0.1",
         "tinybench": "^2.5.0",
-        "tinypool": "^0.5.0",
+        "tinypool": "^0.7.0",
         "vite": "^3.0.0 || ^4.0.0",
-        "vite-node": "0.32.0",
+        "vite-node": "0.34.1",
         "why-is-node-running": "^2.2.2"
       },
       "bin": {
@@ -13206,15 +12889,6 @@
       "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
       "dev": true
     },
-    "node_modules/well-known-symbols": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz",
-      "integrity": "sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
     "node_modules/whatwg-url": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
@@ -13301,15 +12975,6 @@
         "string-width": "^1.0.2 || 2 || 3 || 4"
       }
     },
-    "node_modules/word-wrap": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
-      "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/wrap-ansi": {
       "version": "7.0.0",
       "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
diff --git a/package.json b/package.json
index 98e01666..0af9663f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "web-scrobbler",
-  "version": "3.0.12",
+  "version": "3.0.15",
   "author": "David Šabata <posta@davidsabata.cz>",
   "contributors": [
     "@mountainash (https://mountainash.id.au/)"
@@ -26,11 +26,11 @@
   },
   "homepage": "https://web-scrobbler.com/",
   "dependencies": {
-    "@suid/icons-material": "0.6.3",
+    "@suid/icons-material": "0.6.9",
     "@web-scrobbler/metadata-filter": "3.0.1",
     "blueimp-md5": "2.19.0",
     "stylelint": "13.13.1",
-    "vite": "4.3.9",
+    "vite": "4.4.8",
     "webextension-polyfill": "0.10.0"
   },
   "devDependencies": {
@@ -39,38 +39,38 @@
     "@types/fs-extra": "11.0.1",
     "@types/imagemin": "8.0.1",
     "@types/imagemin-jpegtran": "5.0.1",
-    "@types/node": "20.2.6",
-    "@types/react": "18.2.11",
-    "@types/webextension-polyfill": "0.10.0",
-    "@typescript-eslint/eslint-plugin": "5.59.9",
+    "@types/node": "20.4.8",
+    "@types/react": "18.2.18",
+    "@types/webextension-polyfill": "0.10.1",
+    "@typescript-eslint/eslint-plugin": "6.3.0",
     "archiver": "5.3.1",
     "canvas": "2.11.2",
     "chokidar": "3.5.3",
-    "esbuild": "0.18.0",
-    "eslint": "8.42.0",
+    "esbuild": "0.18.17",
+    "eslint": "8.46.0",
     "eslint-config-web-scrobbler": "2.1.1",
-    "eslint-plugin-react": "7.32.2",
+    "eslint-plugin-react": "7.33.1",
     "eslint-plugin-solid": "0.12.1",
     "eslint-plugin-tsdoc": "0.2.17",
     "fs-extra": "11.1.1",
-    "glob": "10.2.7",
+    "glob": "10.3.3",
     "imagemin": "8.0.1",
     "imagemin-jpegtran": "7.0.0",
     "imagemin-pngquant": "9.0.2",
-    "prettier": "2.8.8",
+    "prettier": "3.0.1",
     "prettier-config-web-scrobbler": "0.1.0",
     "remark": "14.0.3",
     "remark-cli": "11.0.0",
     "remark-preset-lint-recommended": "6.1.3",
-    "sass": "1.63.3",
-    "solid-js": "1.7.6",
+    "sass": "1.64.2",
+    "solid-js": "1.7.9",
     "stylelint-config-web-scrobbler": "0.2.0",
     "tsx": "3.12.7",
-    "typescript": "5.1.3",
+    "typescript": "5.1.6",
     "vite-plugin-conditional-compiler": "0.1.1",
     "vite-plugin-solid": "2.7.0",
-    "vite-plugin-static-copy": "0.16.0",
-    "vitest": "0.32.0"
+    "vite-plugin-static-copy": "0.17.0",
+    "vitest": "0.34.1"
   },
   "engines": {
     "node": ">=18.0.0"
diff --git a/scripts/log.ts b/scripts/log.ts
index 465d6014..672086ec 100644
--- a/scripts/log.ts
+++ b/scripts/log.ts
@@ -1,6 +1,6 @@
 type ColorType = 'success' | 'info' | 'error' | 'warning' | keyof typeof COLORS;
 
-export default function colorLog(message: any, type?: ColorType): void {
+export default function colorLog(message: string, type?: ColorType): void {
 	let color: string = type || COLORS.FgBlack;
 
 	switch (type) {
diff --git a/src/_locales/lt/messages.json b/src/_locales/lt/messages.json
index fb5a5b25..5b8ea678 100644
--- a/src/_locales/lt/messages.json
+++ b/src/_locales/lt/messages.json
@@ -1,568 +1,468 @@
 {
     "optionsTitle": {
-        "message": "Web Scrobbler options",
+        "message": "„Web Scrobbler“ parinktys",
         "description": "Title of options page"
     },
     "optionsGeneral": {
-        "message": "General",
+        "message": "Bendra",
         "description": "'General' section"
     },
     "optionsPermissionsLabel": {
-        "message": "You have not granted Web Scrobbler the permission to access all sites, which means you have to click the extension icon to start scrobbling every time. Click here to grant the permission. Note that in safari the permission will not automatically be granted, but the next time you visit a supported site you will be able to click \"Always Allow on Every Website...\" to grant the permission.",
+        "message": "Nesuteikėte „Web Scrobbler“ leidimo naudotis visomis svetainėmis, todėl kiekvieną kartą turite spustelėti plėtinio piktogramą, kad pradėtumėte skroboti. Spustelėkite čia, kad suteiktumėte leidimą. Atkreipkite dėmesį, kad „Safari“ programoje leidimas nebus suteiktas automatiškai, tačiau kitą kartą apsilankę palaikomoje svetainėje galėsite spustelėti „Visada leisti kiekvienoje svetainėje...“, kad suteiktumėte leidimą.",
         "description": "Label for permissions button"
     },
     "optionUseNotifications": {
-        "message": "Use now playing notifications",
+        "message": "Naudoti dabar grojamus pranešimus",
         "description": "Option label"
     },
     "optionUseNotificationsTitle": {
-        "message": "Show now playing notifications for all supported websites",
+        "message": "Rodyti dabar grojančius pranešimus visose palaikomose svetainėse",
         "description": "Option title"
     },
     "optionUnrecognizedNotifications": {
-        "message": "Notify if track is not recognized",
+        "message": "Pranešti, jei takelis neatpažįstamas",
         "description": "Option label"
     },
     "optionUnrecognizedNotificationsTitle": {
-        "message": "Show notification if track is not recognized by the extension",
+        "message": "Rodyti pranešimą, jei takelis neatpažįstamas pagal plėtinį",
         "description": "Option title"
     },
     "optionScrobblePodcasts": {
-        "message": "Scrobble podcasts",
+        "message": "Skroboti transliacijas",
         "description": "Option label"
     },
     "optionScrobblePodcastsTitle": {
-        "message": "Scrobble podcast episodes",
+        "message": "Skrobuoti tinklalaidės epizodus",
         "description": "Option title"
     },
     "optionsScrobbleBehavior": {
-        "message": "Scrobble behavior",
+        "message": "Skroblo elgesys",
         "description": "'Scrobble behavior' section"
     },
     "optionForceRecognize": {
-        "message": "Force track recognition",
+        "message": "Priversti takelio atpažinimą",
         "description": "Option label"
     },
     "optionForceRecognizeTitle": {
-        "message": "Force recognition of unknown tracks",
+        "message": "Priversti atpažinti nežinomus takelius",
         "description": "Option title"
     },
     "optionScrobbleRecognizedTracks": {
-        "message": "Scrobble recognized or edited tracks (default)",
+        "message": "Skrobuoti atpažintus arba redaguotus takelius (numatytoji)",
         "description": "Option label"
     },
     "optionScrobbleRecognizedTracksTitle": {
-        "message": "Only scrobble tracks if they are recognized or edited",
+        "message": "Skrobuoti tik tuos takelius, jei jie atpažįstami arba redaguojami.",
         "description": "Option title"
     },
     "optionScrobbleEditedTracksOnly": {
-        "message": "Scrobble edited tracks only",
+        "message": "Skrobuoti tik redaguotus takelius",
         "description": "Option label"
     },
     "optionScrobbleEditedTracksOnlyTitle": {
-        "message": "Only scrobble tracks if they are edited",
+        "message": "Skrobuoti takelius, jei jie yra redaguoti.",
         "description": "Option title"
     },
     "optionsHidden": {
-        "message": "Hidden",
+        "message": "Paslėptas",
         "description": "'Hidden' section"
     },
-    "optionScrobblePercent": {
-        "message": "Scrobble at",
-        "description": "Option title"
-    },
     "optionScrobblePercentSuffix": {
-        "message": "of song duration",
+        "message": "dainos trukmė",
         "description": "Option title"
     },
-    "optionYtDesc": {
-        "message": "If you turn off both options, the extension will scrobble YouTube videos from all categories.",
-        "description": "Description of YouTube options"
-    },
     "optionPercentDesc": {
-        "message": "Note that a track will be scrobbled anyway, if it has been played for 4 minutes, regardless of the option value.",
+        "message": "Atkreipkite dėmesį, kad takelis vis tiek bus nuskrobuotas, jei jis bus grojamas 4 minutes, nepriklausomai nuo parinkties reikšmės.",
         "description": "Description of scrobble percent option"
     },
-    "optionYtMusicOnly": {
-        "message": "Scrobble videos from \"Music\" category",
-        "description": "Option title"
-    },
-    "optionYtMusicOnlyTitle": {
-        "message": "Ignore videos that are not in Music category",
-        "description": "Option label"
-    },
     "optionYtEntertainmentOnly": {
-        "message": "Scrobble videos from \"Entertainment\" category",
+        "message": "Skrobuoti vaizdo įrašus iš „Pramogos“ kategorijos",
         "description": "Option label"
     },
     "optionYtEntertainmentOnlyTitle": {
-        "message": "Ignore videos that are not in Entertainment category",
-        "description": "Option title"
-    },
-    "optionYtGetTrackInfoFromYtMusic": {
-        "message": "Use Youtube Music to get track info",
-        "description": "Option label"
-    },
-    "optionYtGetTrackInfoFromYtMusicTitle": {
-        "message": "Use Youtube Music to get track info, if disabled defaults to using description and video title",
-        "description": "Option title"
-    },
-    "optionYtMusicRecognisedOnly": {
-        "message": "Scrobble only videos that are recognized by YouTube Music as music",
-        "description": "Option label"
-    },
-    "optionYtMusicRecognisedOnlyTitle": {
-        "message": "Ignore videos that are not recognised by YouTube Music as music",
+        "message": "Ignoruokite vaizdo įrašus, kurie nėra pramogų kategorijoje",
         "description": "Option title"
     },
     "optionTheme": {
-        "message": "Theme",
+        "message": "Tema",
         "description": "Option label"
     },
     "optionThemeTitle": {
-        "message": "Choose the theme of the extension",
+        "message": "Pasirinkite plėtinio temą",
         "description": "Option title"
     },
     "optionThemeLight": {
-        "message": "Light",
+        "message": "Šviesos",
         "description": "Option label"
     },
     "optionThemeDark": {
-        "message": "Dark",
+        "message": "Tamsos",
         "description": "Option label"
     },
     "optionThemeSystem": {
-        "message": "System",
+        "message": "Sistemos",
         "description": "Option label"
     },
     "optionsAccounts": {
-        "message": "Accounts",
+        "message": "Paskyros",
         "description": "'Accounts' section"
     },
     "accountsSignedInAs": {
-        "message": "You are signed in as $1.",
+        "message": "Esate prisijungę kaip $1.",
         "description": "'Signed in' label"
     },
     "accountsNotSignedIn": {
-        "message": "You are not signed in.",
+        "message": "Jūs nesate prisijungę.",
         "description": "'Signed in' label"
     },
     "accountsProfile": {
-        "message": "Profile",
+        "message": "Profilis",
         "description": "'Signed in' label"
     },
     "accountsSignOut": {
-        "message": "Sign out",
+        "message": "Atsijungti",
         "description": "Button label"
     },
     "accountsSignIn": {
-        "message": "Sign in",
+        "message": "Prisijungti",
         "description": "Button label"
     },
     "accountsScrobblerProps": {
-        "message": "Properties",
+        "message": "Ypatybės",
         "description": "Button label"
     },
     "accountsScrobblerPropsTitle": {
-        "message": "$1 properties",
+        "message": "$1 ypatybės",
         "description": "Button label"
     },
     "accountsUserApiUrl": {
-        "message": "API URL",
+        "message": "API URL'as",
         "description": "Input label"
     },
     "accountsUserApiUrlPlaceholder": {
-        "message": "Custom API URL",
+        "message": "Pasirinktinis API URL'as",
         "description": "Input label"
     },
     "accountsUserToken": {
-        "message": "Token",
+        "message": "Žyma",
         "description": "Input label"
     },
     "accountsUserTokenPlaceholder": {
-        "message": "Custom token",
+        "message": "Pasirinktinis žymuo",
         "description": "Input label"
     },
     "optionsOptions": {
-        "message": "Options",
+        "message": "Parinktys",
         "description": "'Options' section"
     },
     "optionsEdits": {
-        "message": "Edits",
+        "message": "Redagavimai",
         "description": "'Edits' section"
     },
     "optionsEditedTracks": {
-        "message": "Edited tracks",
+        "message": "Redaguojamos takeliai",
         "description": "'Edited tracks' header"
     },
     "optionsEditedTracksDesc": {
-        "message": "This extension stores edited tracks.",
+        "message": "Šis plėtinys saugo redaguotus takelius.",
         "description": "Description of edited tracks"
     },
     "optionsEditedTracksPopupTitle": {
-        "message": "$1 edited tracks",
+        "message": "$1 redaguoti takeliai",
         "description": "'Edited tracks' header"
     },
     "optionsRegexEdits": {
-        "message": "Regex/Bulk edits",
-        "description": "'Regex/Bulk edits' header"
-    },
-    "optionsRegexEditsDesc": {
-        "message": "This extension stores regex/bulk edits.",
-        "description": "Description of regex/bulk edits"
-    },
-    "optionsRegexEditsPopupTitle": {
-        "message": "$1 regex/bulk edits",
+        "message": "Regeksų/masiniai redagavimai",
         "description": "'Regex/Bulk edits' header"
     },
     "optionsViewEdited": {
-        "message": "View",
+        "message": "Peržiūrėti",
         "description": "Button to view edited tracks"
     },
     "optionsExportEdited": {
-        "message": "Export",
+        "message": "Eksportuoti",
         "description": "Button to export edited tracks"
     },
     "optionsImportEdited": {
-        "message": "Import",
+        "message": "Importuoti",
         "description": "Button to import edited tracks"
     },
     "optionsConnectors": {
-        "message": "Connectors",
+        "message": "Jungtys",
         "description": "'Connectors' section"
     },
     "optionsEnableDisableHint": {
-        "message": "Click on the checkbox to enable/disable connectors.",
+        "message": "Spustelėkite žymimąjį langelį, kad įjungtumėte/išjungtumėte sąsajas.",
         "description": "Enable/disable hint"
     },
     "optionsCustomPatternsHint": {
-        "message": "Click on the gear icon to configure custom URL patterns for connectors.",
+        "message": "Spustelėkite krumpliaračio piktogramą, kad sukonfigūruotumėte pasirinktinius jungčių URL šablonus.",
         "description": "Description of how to configure custom URL patterns"
     },
     "optionsSupportedWebsites": {
-        "message": "Supported websites",
+        "message": "Palaikomos svetainės",
         "description": "'Supported websites' header"
     },
     "optionsToggle": {
-        "message": "Toggle",
+        "message": "Perjungti",
         "description": "Label of toggle button"
     },
     "optionsLoadingConnectorOptions": {
-        "message": "Loading connector options...",
+        "message": "Kraunamos jungties parinktys…",
         "description": "Loading connector options message"
     },
     "learnMoreLabel": {
-        "message": "Learn more",
+        "message": "Sužinokite daugiau",
         "description": "Learn more label"
     },
     "contactTitle": {
-        "message": "Contact",
+        "message": "Kontaktuoti",
         "description": "'Contact' section"
     },
     "contactGitHubDesc": {
-        "message": "Report an issue and contribute",
+        "message": "Pranešti apie problemą ir prisidėti",
         "description": "Description for GitHub section"
     },
     "contactTwitterDesc": {
-        "message": "Keep up with the updates and for quick chat",
+        "message": "Sekite atnaujinimus ir greitų pokalbių",
         "description": "Description for Twitter section"
     },
     "contactPrivacyPolicyDesc": {
-        "message": "View the privacy policy",
+        "message": "Peržiūrėti privatumo politiką",
         "description": "Description for privacy section"
     },
     "faqTitle": {
-        "message": "FAQ",
+        "message": "DUK",
         "description": "'FAQ' section"
     },
     "faqQuestion1": {
-        "message": "How can I start using the extension?",
+        "message": "Kaip galiu pradėti naudoti plėtinį?",
         "description": "Question #1"
     },
     "faqAnswer1a": {
-        "message": "You should click on a notification that is shown when the extension is loaded the first time. Then, you should grant access to your accounts.",
+        "message": "Turite spustelėti pranešimą, kuris rodomas, kai plėtinys pakraunamas pirmą kartą. Tada turėtumėte suteikti prieigą prie savo paskyrų.",
         "description": "Answer #1"
     },
     "faqAnswer1b": {
-        "message": "Note: In some cases, the notification won't be shown, e.g. on Mac OS if Chrome is running in full-screen mode; the extension will open a tab where you can grant access to your accounts.",
+        "message": "Pastaba: kai kuriais atvejais pranešimas nebus rodomas, pvz., „Mac OS“, jei „Chrome“ veikia viso ekrano režimu; plėtinys atidarys skirtuką, kuriame galėsite suteikti prieigą prie savo paskyrų.",
         "description": "Answer #1"
     },
     "faqQuestion2": {
-        "message": "How do I temporarily disable scrobbling?",
+        "message": "Kaip laikinai išjungti skrobliavimą?",
         "description": "Question #2"
     },
     "faqAnswer2a": {
-        "message": "You can do that by right-clicking on the green extension icon in the extension bar. Using the context menu you can disable the connector for the current web service.",
+        "message": "Tai galite padaryti dešiniuoju pelės klavišu spustelėję žalią plėtinio piktogramą plėtinių juostoje. Naudodamiesi kontekstiniu meniu galite išjungti dabartinės interneto paslaugos jungtį.",
         "description": "Answer #2"
     },
     "faqAnswer2b": {
-        "message": "Use the checkboxes on the options page to disable certain connectors, or the \"Toggle\" checkbox to disable scrobbling globally.",
+        "message": "Naudokite žymimuosius langelius parinkčių puslapyje, norėdami išjungti tam tikras jungtis, arba žymimąjį langelį „Perjungti“, kad išjungtumėte skrobliavimą visuotinai.",
         "description": "Answer #2"
     },
     "faqQuestion3": {
-        "message": "The track was not recognized! Can you fix it?",
+        "message": "Takelis nebuvo atpažintas! Ar galite tai ištaisyti?",
         "description": "Question #3"
     },
     "faqAnswer3a": {
-        "message": "When a track cannot be recognized, a gray icon with question mark appears in the extension bar. You can click on this icon and input correct data in the opened popup window.",
+        "message": "Kai takelio negalima atpažinti, plėtinio juostoje pasirodo pilka piktograma su klausimo ženklu. Galite spustelėti ant šios piktogramos ir atvertame iškylančiajame lange įvesti teisingus duomenis.",
         "description": "Answer #3"
     },
     "faqAnswer3b": {
-        "message": "Also, there's an option called \"Force track recognition\" that makes the extension force scrobbling the track even if the track is not validated by Last.fm.",
+        "message": "Be to, yra parinktis „Priversti takelio atpažinimą“, dėl kurios plėtinys priverčia skroboti takelį, net jei takelis nepatvirtintas „Last.fm“.",
         "description": "Answer #3"
     },
-    "faqQuestion4": {
-        "message": "Some music on Bandcamp cannot be scrobbled. Is it possible to fix this?",
-        "description": "Question #4"
-    },
     "faqAnswer4a": {
-        "message": "Looks like the music is hosted on a custom domain and the extension cannot detect whether it’s Bandcamp or not.",
-        "description": "Answer #4"
-    },
-    "faqAnswer4b": {
-        "message": "As a workaround, configure the extension to work with custom domains as follows:",
-        "description": "Answer #4"
-    },
-    "faqAnswer4b1": {
-        "message": "Open the extension setting page and expand the “Options” section.",
-        "description": "Answer #4"
-    },
-    "faqAnswer4b2": {
-        "message": "Find the Bandcamp connector in the list of supported services.",
+        "message": "Atrodo, kad muzika patalpinta pasirinktiniame domene ir plėtinys negali nustatyti, ar tai „Bandcamp“, ar ne.",
         "description": "Answer #4"
     },
     "faqAnswer4b3": {
-        "message": "Click on the gear icon near the connector label.",
-        "description": "Answer #4"
-    },
-    "faqAnswer4b4": {
-        "message": "Add URL pattern that matches the Bandcamp custom domain URL and apply the changes.",
-        "description": "Answer #4"
-    },
-    "faqAnswer4c": {
-        "message": "You can learn more about the custom URL patterns <a target='_blank' href='https://github.com/web-scrobbler/web-scrobbler/wiki/Custom-URL-patterns'>here</a>.",
+        "message": "Spauskite krumpliaračio piktogramą šalia jungties etiketės.",
         "description": "Answer #4"
     },
     "faqQuestion5": {
-        "message": "Will you add support for scrobbling at ____ ?",
+        "message": "Ar pridėsite palaikymą skroblinimui ____ ?",
         "description": "Question #5"
     },
     "faqAnswer5": {
-        "message": "Open a <a href=\"https://github.com/web-scrobbler/web-scrobbler/issues\" target=\"_blank\">new issue</a> on GitHub with your request, and we'll tell you if we can add support for the website or not. Also, you can add support for the website by forking the <a href=\"http://github.com/web-scrobbler/web-scrobbler\">GitHub repository</a> and sending us a pull request.",
+        "message": "Atidarykite <a href=\"https://github.com/web-scrobbler/web-scrobbler/issues\" target=\"_blank\">naują problemą</a> „GitHub“ svetainėje su savo prašymu ir mes jums pasakysime, ar galime pridėti svetainės palaikymą, ar ne. Be to, galite pridėti svetainės palaikymą šakodami <a href=\"http://github.com/web-scrobbler/web-scrobbler\">„GitHub“ repozitoriją</a> ir siųsdami mums traukimo užklausą.",
         "description": "Answer #5"
     },
     "faqQuestion6": {
-        "message": "Will you add ____ functionality?",
+        "message": "Ar pridėsite ____ funkcionalumą?",
         "description": "Question #6"
     },
     "faqAnswer6": {
-        "message": "Possibly, if it makes sense. But if you want me to add some not-that-useful-but-really-cool functions, you'll probably get disappointed.",
+        "message": "Galbūt, jei tai prasminga. Bet jei norite, kad pridėčiau keletą ne tokių naudingų, bet tikrai šaunių funkcijų, tikriausiai nusivilsite.",
         "description": "Answer #6"
     },
     "faqQuestion7": {
-        "message": "Who is the author?",
+        "message": "Kas yra autorius?",
         "description": "Question #7"
     },
     "faqAnswer7": {
-        "message": "The original author of this extension is David Šabata. Now this extension is developed and maintained by the Web Scrobbler Team.",
+        "message": "Originalus šio plėtinio autorius yra Deividas Šabatas. Dabar šį plėtinį kuria ir prižiūri „Web Scrobbler“ komanda.",
         "description": "Answer #7"
     },
     "optionsAbout": {
-        "message": "About",
+        "message": "Apie",
         "description": "'About' section"
     },
-    "aboutChangelog": {
-        "message": "The changelog of current version is available <a id='latest-release' target='_blank' href='#'>here</a>. For the full changelog please visit <a target='_blank' href='https://github.com/web-scrobbler/web-scrobbler/releases'>this page</a>.",
-        "description": "'About' section text"
-    },
     "aboutExtensionDesc": {
-        "message": "Web Scrobbler is a browser extension created for people who listen to music online through their browser, and would like to keep an updated playback history using scrobbling services, such as Last.fm, Libre.fm and ListenBrainz.",
+        "message": "„Web Scrobbler“ yra naršyklės plėtinys, sukurtas žmonėms, kurie klausosi muzikos internete per naršyklę ir norėtų išsaugoti atnaujintą grojimo istoriją, naudodamiesi skrobliavimo paslaugomis, tokiomis kaip „Last.fm“, „Libre.fm“ ir „ListenBrainz“.",
         "description": "'About' section text"
     },
     "contributorsTitle": {
-        "message": "Contributors",
+        "message": "Bendradarbiai",
         "description": "'Contributors' header"
     },
-    "contributorsText": {
-        "message": "You can find the list of contributors <a href=\"https://github.com/web-scrobbler/web-scrobbler/graphs/contributors\">right on the GitHub</a>",
-        "description": "'About' section text"
-    },
     "contributorsContribute": {
-        "message": "Want to contribute? See all the ways you can contribute to the project at <a href=\"https://web-scrobbler.com#contributing\" target=\"_blank\" rel=\"noopener noreferrer\">our website</a>.",
+        "message": "Norite prisidėti? Peržiūrėkite visus būdus, kaip galite prisidėti prie projekto, <a href=\"https://web-scrobbler.com#contributing\" target=\"_blank\" rel=\"noopener noreferrer\">mūsų svetainėje</a>.",
         "description": "'About' section text"
     },
     "showSomeLoveTitle": {
-        "message": "Show some love",
+        "message": "Rodyti šiek tiek meilės",
         "description": "'Show some love' section"
     },
     "showSomeLoveFundingCampaign": {
-        "message": "Over time a significant backlog of issues has been built up in the Web Scrobbler repository. From mid-August 2023 until mid-March 2024 one of our main developers will be available to work full-time on the project at a reduced rate. Roughly speaking, for every $$1500 we raise, we can pay for one month of full-time work, up to around $$9-10k. If you want to support this campaign and help us run through our backlog and make Web Scrobbler even better than it has ever been, you can use the button below. We remain committed to keeping Web Scrobbler and all of its features completely free forever. Please help spread the word.",
+        "message": "Laikui einant, „Web Scrobbler“ repozitorijoje susikaupė nemažai neišspręstų problemų. Nuo 2023 m. rugpjūčio vidurio iki 2024 m. kovo vidurio vienas iš mūsų pagrindinių programuotojų galės dirbti projekte visą darbo dieną už sumažintą kainą. Grubiai tariant, už kiekvieną surinktą 1500 dolerių sumą galėsime sumokėti už vieną mėnesį darbo visą darbo dieną, t. y. maždaug 9-10 tūkst. dolerių. Jei norite palaikyti šią akciją ir padėti mums įveikti mūsų atsilikimą bei padaryti „Web Scrobbler“ dar geresnį nei kada nors anksčiau, galite pasinaudoti toliau nurodytu mygtuku. Esame pasiryžę išlaikyti „Web Scrobbler“ ir visas jos funkcijas visiškai nemokamas amžinai. Prašome padėti skleisti šią žinią.",
         "description": "Temporary funding campaign"
     },
     "showSomeLoveText1": {
-        "message": "Unlike other extensions, this one does not contain any flashing banners or sneaky ads.",
+        "message": "Skirtingai nei kituose plėtiniuose, šiame nėra jokių mirksinčių reklaminių skydelių ar klastingų reklamų.",
         "description": ""
     },
     "showSomeLoveText2": {
-        "message": "The extension is free, and will always be free. But if you want to support development of the extension, you can use the button below.",
+        "message": "Plėtinys – nemokamas ir visada bus nemokamas. Tačiau jei norite paremti plėtinio kūrimą, galite pasinaudoti toliau esančiu mygtuku.",
         "description": ""
     },
     "donationButtonLabel": {
-        "message": "Support us on OpenCollective",
+        "message": "Palaikykite mus „OpenCollective“",
         "description": "The donation button label"
     },
-    "customPatterns": {
-        "message": "URL patterns",
-        "description": "'URL patterns' section"
-    },
     "customPatternsHint": {
-        "message": "Add URL patterns that the connector should match below.",
+        "message": "Pridėkite URL šablonus, kurias jungtis turėtų atitikti toliau.",
         "description": "Popup hint"
     },
     "customPatternsAdd": {
-        "message": "Add pattern",
+        "message": "Pridėti šabloną",
         "description": "Add button"
     },
     "albumTooltip": {
-        "message": "From \"$1\" album",
+        "message": "Iš „$1“ albumo",
         "description": "Tooltip text"
     },
     "buttonOk": {
-        "message": "OK",
+        "message": "Gerai",
         "description": "OK button label"
     },
     "buttonCancel": {
-        "message": "Cancel",
+        "message": "Atšaukti",
         "description": "Cancel button label"
     },
     "buttonReset": {
-        "message": "Reset",
+        "message": "Nustatyti iš naujo",
         "description": "Reset button label"
     },
     "buttonClear": {
-        "message": "Clear",
+        "message": "Išvalyti",
         "description": "Clear button label"
     },
     "noItemsInCache": {
-        "message": "No items in cache.",
+        "message": "Nėra elementų talpykloje.",
         "description": "Popup hint"
     },
     "getStartedHeader": {
-        "message": "Play some music to get started",
+        "message": "Grokite muziką, kad pradėtumėte",
         "description": "The header of 'Get started' popup"
     },
     "getStartedSubheader": {
-        "message": "Is it already playing?",
+        "message": "Ar tai jau groja?",
         "description": "The subheader of 'Get started' popup"
     },
     "getStartedSiteChanged": {
-        "message": "In most cases this means the site has changed somehow. The change does not have to be visible to user, but means a lot to the extension.",
+        "message": "Dažniausiai tai reiškia, kad svetainė kažkaip pasikeitė. Pokytis neturi būti matomas naudotojui, tačiau plėtiniui tai reiškia labai daug.",
         "description": "Description of why track is not recognized"
     },
     "getStartedSubmitIssue": {
-        "message": "The connector code for this specific website needs to be updated. You can navigate to the <a href=\"https://github.com/web-scrobbler/web-scrobbler/issues\" target=\"_blank\">list of issues</a> and see if this website is already reported. If it is not, you can submit a new issue describing what's wrong, what's expected behavior and what's happening instead.",
+        "message": "Reikia atnaujinti šios svetainės jungties kodą. Galite naršyti <a href=\"https://github.com/web-scrobbler/web-scrobbler/issues\" target=\"_blank\">problemų sąraše</a> ir pažiūrėti, ar apie šią svetainę jau pranešta. Jei ne, galite pateikti naują problemą, apibūdindami, kas negerai, kokio elgesio tikimasi ir kas vyksta vietoj to.",
         "description": "Description of how to submit new issue"
     },
     "serviceErrorHeader": {
-        "message": "Service error",
+        "message": "Paslaugos klaida",
         "description": "The header of 'error' popup"
     },
     "serviceErrorDesc": {
-        "message": "Looks like something went wrong while scrobbling the music. Please open the options page and try to reauthenticate with services. If reauthentication doesn't help, and you still see this message, please create <a href=\"https://github.com/web-scrobbler/web-scrobbler/issues\" target=\"_blank\">a new issue</a> at the GitHub project page.",
+        "message": "Atrodo, kad kažkas nepavyko, kol buvo skrobbuojama muzika. Atidarykite pasirinkčių puslapį ir pabandykite iš naujo autentifikuoti su paslaugomis. Jei pakartotinis autentiškumo nepadeda ir vis dar matote šį pranešimą, sukurkite <a href=\"https://github.com/web-scrobbler/web-scrobbler/issues\" target=\"_blank\">naują problemą</a> „GitHub“ projekto puslapyje.",
         "description": "The description of service error"
     },
     "serviceErrorAdblock": {
-        "message": "Note that some adblockers may interfere with the extension. If you have any adblocker installed, try to disable it and see if it helps. If you are using uBlock Origin, you can add an exception for last.fm by adding <code>@@||ws.audioscrobbler.com</code> under \"My filters\" tab. Other adblockers may have similar functionality.",
+        "message": "Atkreipkite dėmesį, kad kai kurie reklamos blokatoriai gali trukdyti plėtiniui. Jei turite įdiegtą reklamos blokavimo programą, pabandykite išjungti ją ir pažiūrėkite, ar tai padės. Jei naudojate „uBlock Origin“, galite pridėti išimtį „last.fm“, į skirtuką „Mano filtrai“ pridėdami <code>@@|||ws.audioscrobbler.com</code>. Kiti reklamos blokatoriai gali turėti panašią funkciją.",
         "description": "The description of service error"
     },
     "disabledSiteHeader": {
-        "message": "This website is turned off",
+        "message": "Ši svetainė yra išjungta",
         "description": "The header of 'disabled' popup"
     },
     "disabledSiteDesc": {
-        "message": "The extension won't scrobble music from this website until you turn it on in the extension options.",
+        "message": "Šis plėtinys neskrobs muzikos iš šios svetainės, kol jo neįjungsite plėtinio parinktyse.",
         "description": "The description of 'disabled' popup"
     },
     "disabledSiteButton": {
-        "message": "Open options page",
+        "message": "Atidaryti parinkčių puslapį",
         "description": "Button label"
     },
     "unsupportedWebsiteHeader": {
-        "message": "This website is not supported",
+        "message": "Ši svetainė nėra palaikoma",
         "description": "The header of 'unsupported' popup"
     },
     "unsupportedWebsiteDesc": {
-        "message": "Web Scrobbler does not support scrobbling from this website.",
+        "message": "„Web Scrobbler“ nepalaiko skroblinimo iš šios svetainės.",
         "description": "The description of 'unsupported' popup"
     },
     "unsupportedWebsiteDesc2": {
-        "message": "Some Google websites supported by the extension (e.g. Google Play Music, YouTube) can be blocked due to an ExtensionSettings policy.",
+        "message": "Kai kurios plėtiniu palaikomos „Google“ svetainės (pvz., „Google Play Music“, „YouTube“) gali būti blokuojamos dėl plėtinio nustatymų politikos.",
         "description": "The description of 'unsupported' popup"
     },
     "unsupportedWebsiteUpdateNote": {
-        "message": "If the extension recently updated sites may show as unsupported until you refresh the page.",
+        "message": "Jei plėtinys neseniai atnaujintas, svetainės gali būti rodomos kaip nepalaikomos, kol atnaujinsite puslapį.",
         "description": "The description of 'unsupported' popup"
     },
     "infoLove": {
-        "message": "Love track",
+        "message": "Mylėti takelį",
         "description": "Label of love/unlove button"
     },
     "infoUnlove": {
-        "message": "Unlove track",
+        "message": "Nemylėti takelio",
         "description": "Label of love/unlove button"
     },
     "infoEditTitle": {
-        "message": "Edit track metadata",
+        "message": "Redaguoti takelio metaduomenis",
         "description": "Title of edit button"
     },
     "infoEditUnableTitle": {
-        "message": "You cannot edit this track",
+        "message": "Negalite redaguoti šio takelio",
         "description": "Title of edit button"
     },
     "infoEditTitleShort": {
-        "message": "Edit",
+        "message": "Redaguoti",
         "description": "Title of edit button, should be short for mobile button label"
     },
     "infoEditUnableTitleShort": {
-        "message": "Can't Edit",
+        "message": "Negalima redaguoti",
         "description": "Title of edit button, should be short for mobile button label"
     },
     "infoSwapTitle": {
-        "message": "Swap title and artist",
+        "message": "Sukeisti pavadinimą ir atlikėją",
         "description": "Title of swap button"
     },
     "infoSwapUnableTitle": {
-        "message": "You cannot swap empty track info",
+        "message": "Negalite keisti tuščio takelio informacijos",
         "description": "Title of swap button"
     },
-    "infoSwapTitleShort": {
-        "message": "Swap title/artist",
-        "description": "Title of swap button, should be short for mobile button label"
-    },
-    "infoSwapUnableTitleShort": {
-        "message": "Can't swap info",
-        "description": "Title of swap button, should be short for mobile button label"
-    },
-    "infoRegexTitle": {
-        "message": "Regex/Bulk edit mode",
-        "description": "Title of regex/bulk edit button"
-    },
-    "infoRegexTitleShort": {
-        "message": "Regex/Bulk edit",
-        "description": "Title of regex/bulk edit button, should be short for mobile button label"
-    },
     "infoEditedWarning": {
         "message": "Šis takelis buvo redaguotas. Regikso redagavimai netaikomi redaguotiems takeliams, ir peržiūra, kurią matote čia, gali būti netiksli.",
         "description": "Warning message to user if bulk editing on a previously edited track"
     },
-    "infoSubmitTitle": {
-        "message": "Submit changes",
-        "description": "Title of submit button"
-    },
-    "infoSubmitUnableTitle": {
-        "message": "You cannot submit empty track info",
-        "description": "Title of submit button"
-    },
     "infoSubmitTitleShort": {
         "message": "Pateikti",
         "description": "Title of submit button, should be short for mobile button label"
@@ -572,11 +472,11 @@
         "description": "Title of submit button, should be short for mobile button label"
     },
     "infoRevertTitle": {
-        "message": "Revert changes",
+        "message": "Grąžinti pakeitimus",
         "description": "Title of revert button"
     },
     "infoRevertUnableTitle": {
-        "message": "You cannot revert this track",
+        "message": "Negalite atstatyti šio takelio",
         "description": "Title of revert button"
     },
     "infoRevertTitleShort": {
@@ -588,17 +488,13 @@
         "description": "Title of revert button, should be short for mobile button label"
     },
     "infoSkipTitle": {
-        "message": "Don't scrobble current track",
+        "message": "Neskrobuoti dabartinio takelio",
         "description": "Title of skip button"
     },
     "infoSkipUnableTitle": {
-        "message": "You cannot skip this track",
+        "message": "Negalite praleisti šio takelio",
         "description": "Title of skip button"
     },
-    "infoSkippedTitle": {
-        "message": "You skipped this track",
-        "description": "Title of unskip button"
-    },
     "infoSkipTitleShort": {
         "message": "Praleisti",
         "description": "Title of skip button, should be short for mobile button label"
@@ -612,167 +508,103 @@
         "description": "Title of unskip button, should be short for mobile button label"
     },
     "infoOpenAlbumArt": {
-        "message": "Open album art in new tab",
+        "message": "Atidaryti albumo paveikslėlį naujame skirtuke",
         "description": "Title of album image"
     },
     "infoArtistPlaceholder": {
-        "message": "Artist",
+        "message": "Atlikėjas",
         "description": "Placeholder of artist input"
     },
     "infoTrackPlaceholder": {
-        "message": "Track",
+        "message": "Takelis",
         "description": "Placeholder of track input"
     },
     "infoAlbumPlaceholder": {
-        "message": "Album (optional)",
+        "message": "Albumas (pasirinktinai)",
         "description": "Placeholder of album input"
     },
-    "infoAlbumArtistPlaceholder": {
-        "message": "Album artist (optional)",
-        "description": "Placeholder of album artist input"
-    },
     "infoSearchLabel": {
         "message": "Paieška",
         "description": "Label of regex edit search input"
     },
-    "infoReplaceLabel": {
-        "message": "Replace",
-        "description": "Label of regex edit replace input"
-    },
-    "infoPreviewLabel": {
-        "message": "Preview",
-        "description": "Label of regex edit preview output"
-    },
-    "infoArtistLabel": {
-        "message": "Artist",
-        "description": "Label of artist input row"
-    },
-    "infoTrackLabel": {
-        "message": "Track",
-        "description": "Label of track input row"
-    },
-    "infoAlbumLabel": {
-        "message": "Album",
-        "description": "Label of album input row"
-    },
-    "infoAlbumArtistLabel": {
-        "message": "Album artist",
-        "description": "Label of album artist input row"
-    },
-    "infoViewArtistPage": {
-        "message": "View artist page: $1",
-        "description": "Placeholder of album input"
-    },
-    "infoViewAlbumPage": {
-        "message": "View album page: $1",
-        "description": "Placeholder of album input"
-    },
-    "infoViewTrackPage": {
-        "message": "View track page: $1",
-        "description": "Placeholder of album input"
-    },
-    "infoYourScrobbles": {
-        "message": "Your scrobbles: $1",
-        "description": "Label for user play count"
-    },
     "pageActionBase": {
-        "message": "This site is supported for scrobbling",
+        "message": "Ši svetainė yra palaikoma skrobavimo",
         "description": "`base` page action title"
     },
     "pageActionLoading": {
-        "message": "Looking up $1",
+        "message": "Ieškomas $1",
         "description": "`loading` page action title"
     },
-    "pageActionPlaying": {
-        "message": "Now playing $1",
-        "description": "`playing` page action title"
-    },
     "pageActionScrobbled": {
-        "message": "Scrobbled $1",
+        "message": "Nuskrobliuota $1",
         "description": "`scrobbled` page action title"
     },
     "pageActionSkipped": {
-        "message": "Skipped $1",
+        "message": "Praleista $1",
         "description": "`skipped` page action title"
     },
     "pageActionIgnored": {
-        "message": "Ignored $1",
+        "message": "Ignoruota $1",
         "description": "`ignored` page action title"
     },
     "pageActionDisabled": {
-        "message": "This site is supported for scrobbling, but you disabled it",
+        "message": "Ši svetainė yra palaikoma skrobavimo, bet tu jį išjungei",
         "description": "`disabled` page action title"
     },
     "pageActionUnknown": {
-        "message": "The track is not recognized. Click to submit correct info.",
+        "message": "Takelis – neatpažįstamas. Spustelėkite, kad pateiktumėte teisingą informaciją.",
         "description": "`unknown` page action title"
     },
     "pageActionError": {
-        "message": "A service error occurred. Click for more information.",
+        "message": "Įvyko paslaugos klaida. Spustelėkite, kad gautumėte daugiau informacijos.",
         "description": "`loading` page action title"
     },
-    "pageActionUnsupported": {
-        "message": "Web Scrobbler does not support this website.",
-        "description": "`unsupported` page action title"
-    },
-    "pageActionLoved": {
-        "message": "You loved $1",
-        "description": "`unsupported` page action title"
-    },
-    "pageActionUnloved": {
-        "message": "You unloved $1",
-        "description": "`unsupported` page action title"
-    },
     "menuDisableConnector": {
-        "message": "Disable $1 connector",
+        "message": "Išjungti $1 jungtį",
         "description": "Context menu item"
     },
     "menuEnableConnector": {
-        "message": "Enable $1 connector",
+        "message": "Įjungti $1 jungtį",
         "description": "Context menu item"
     },
     "menuDisableUntilTabClosed": {
-        "message": "Disable $1 connector until tab is closed",
+        "message": "Išjungti $1 jungtį, kol skirtukas bus uždarytas",
         "description": "Context menu item"
     },
     "notificationConnectAccounts": {
-        "message": "Connect your accounts",
+        "message": "Prijunkite savo paskyras",
         "description": "Notification title"
     },
     "notificationConnectAccountsText": {
-        "message": "Click the notification to connect your accounts.",
+        "message": "Spustelėkite pranešimą, kad prijungtumėte savo paskyras.",
         "description": "Notification text"
     },
     "notificationAuthError": {
-        "message": "Authentication error",
+        "message": "Autentifikavimo klaida",
         "description": "Notification title"
     },
     "notificationUnableSignIn": {
-        "message": "Unable to sign in to $1. Please try later.",
+        "message": "Nepavyko prisijungti prie $1. Prašome pabandyti vėliau.",
         "description": "Notification text"
     },
     "notificationNotRecognized": {
-        "message": "The track is not recognized",
+        "message": "Takelis neatpažįstamas",
         "description": "Notification title"
     },
     "notificationNotRecognizedText": {
-        "message": "Click on the icon in the extensions bar to correct and submit track info.",
+        "message": "Spustelėkite piktogramą plėtinių juostoje, kad pataisytumėte ir pateiktumėte takelio informaciją.",
         "description": "Notification text"
     },
     "hotkeyToggleConnector": {
-        "message": "Toggle scrobbling for current website",
+        "message": "Perjungti skrobliavimą dabartinėje svetainėje",
         "description": "Hotkey label"
     },
     "hotkeyLoveSong": {
-        "message": "Love now playing song",
-        "description": "Hotkey label"
-    },
-    "hotkeyUnloveSong": {
-        "message": "Unlove now playing song",
+        "message": "Mylėti dabar grojanti daina",
         "description": "Hotkey label"
     },
     "extDescription": {
-        "message": "Scrobble music all around the web!",
+        "message": "Skrobuokite muziką visame internete!",
         "description": "Description of the extension"
     }
-}
\ No newline at end of file
+}
diff --git a/src/connectors/deezer-dom-inject.ts b/src/connectors/deezer-dom-inject.ts
index 734bc197..071d3cbc 100644
--- a/src/connectors/deezer-dom-inject.ts
+++ b/src/connectors/deezer-dom-inject.ts
@@ -1,3 +1,5 @@
+import { State } from '@/core/types';
+
 deezerInitConnector();
 
 function deezerInitConnector() {
@@ -23,7 +25,16 @@ function deezerAddEventListeners() {
 	if (!('Events' in window)) {
 		return;
 	}
-	const ev = window.Events as any;
+	const ev = window.Events as {
+		player: {
+			play: unknown;
+			playing: unknown;
+			paused: unknown;
+			resume: unknown;
+			finish: unknown;
+		};
+		subscribe: (_: unknown, __: unknown) => void;
+	};
 	ev.subscribe(ev.player.play, deezerSendEvent);
 	ev.subscribe(ev.player.playing, deezerSendEvent);
 	ev.subscribe(ev.player.paused, deezerSendEvent);
@@ -40,15 +51,33 @@ function deezerSendEvent() {
 			isPlaying: deezerIsPlaying(),
 			isPodcast: deezerIsPodcast(),
 		},
-		'*'
+		'*',
 	);
 }
 
+interface DeezerMedia {
+	__TYPE__: string;
+	EXTERNAL?: unknown;
+	SNG_ID?: string;
+	SNG_TITLE?: string;
+	VERSION?: string;
+	ART_NAME?: string;
+	ALB_TITLE?: string;
+	ALB_PICTURE: string;
+	SHOW_NAME?: string;
+	EPISODE_TITLE?: string;
+	EPISODE_ID?: string;
+}
+
 function deezerGetCurrentMediaInfo() {
 	if (!('dzPlayer' in window)) {
 		return;
 	}
-	const player = window.dzPlayer as any;
+	const player = window.dzPlayer as {
+		getCurrentSong: () => DeezerMedia;
+		getPosition: () => number | null;
+		getDuration: () => number | null;
+	};
 	const currentMedia = player.getCurrentSong();
 
 	// Radio stations don't provide track info
@@ -60,13 +89,7 @@ function deezerGetCurrentMediaInfo() {
 	const currentTime = player.getPosition();
 	const duration = player.getDuration();
 
-	let trackInfo: {
-		artist: any;
-		track: any;
-		uniqueID: any;
-		duration?: any;
-		currentTime?: any;
-	} | null = null;
+	let trackInfo: State | null = null;
 
 	switch (mediaType) {
 		case 'episode': {
@@ -83,7 +106,7 @@ function deezerGetCurrentMediaInfo() {
 	if (!trackInfo) {
 		Util.debugLog(
 			`Unable to load track info for ${mediaType} media type`,
-			'warn'
+			'warn',
 		);
 		return null;
 	}
@@ -94,7 +117,7 @@ function deezerGetCurrentMediaInfo() {
 	return trackInfo;
 }
 
-function deezerGetTrackInfo(currentMedia: any) {
+function deezerGetTrackInfo(currentMedia: DeezerMedia) {
 	let trackTitle = currentMedia.SNG_TITLE;
 	const trackVersion = currentMedia.VERSION;
 	if (trackVersion) {
@@ -110,7 +133,7 @@ function deezerGetTrackInfo(currentMedia: any) {
 	};
 }
 
-function deezerGetEpisodeInfo(currentMedia: any) {
+function deezerGetEpisodeInfo(currentMedia: DeezerMedia) {
 	return {
 		artist: currentMedia.SHOW_NAME,
 		track: currentMedia.EPISODE_TITLE,
@@ -122,14 +145,16 @@ function deezerIsPlaying() {
 	if (!('dzPlayer' in window)) {
 		return;
 	}
-	return (window.dzPlayer as any).isPlaying();
+	return (window.dzPlayer as { isPlaying: () => boolean }).isPlaying();
 }
 
 function deezerIsPodcast() {
 	if (!('dzPlayer' in window)) {
 		return;
 	}
-	const currentMedia = (window.dzPlayer as any).getCurrentSong();
+	const currentMedia = (
+		window.dzPlayer as { getCurrentSong: () => DeezerMedia }
+	).getCurrentSong();
 	return currentMedia.__TYPE__ === 'episode';
 }
 
diff --git a/src/connectors/deezer.ts b/src/connectors/deezer.ts
index b7d37f5f..0d27d774 100644
--- a/src/connectors/deezer.ts
+++ b/src/connectors/deezer.ts
@@ -1,3 +1,4 @@
+import { State } from '@/core/types';
 export {};
 
 const deezerFilter = MetadataFilter.createRemasteredFilter();
@@ -18,7 +19,7 @@ Connector.onScriptEvent = (event) => {
 	switch (event.data.type) {
 		case 'DEEZER_STATE':
 			({ trackInfo, isPlaying, isPodcast } = event.data as {
-				trackInfo: any;
+				trackInfo: State;
 				isPlaying: boolean;
 				isPodcast: boolean;
 			});
diff --git a/src/connectors/eggs-dom-inject.ts b/src/connectors/eggs-dom-inject.ts
index b98722da..1806eec9 100644
--- a/src/connectors/eggs-dom-inject.ts
+++ b/src/connectors/eggs-dom-inject.ts
@@ -16,10 +16,20 @@ if (eggsIsArtistPage) {
 	observer.observe(document.body, { childList: true });
 } else {
 	if ('player' in window) {
-		(window.player as any).addEventListener(
-			'onStateChange',
-			eggsOnYoutubeSongStateChange
-		);
+		(
+			window.player as {
+				addEventListener: (
+					_: string,
+					__: (ev: {
+						data: number;
+						target: {
+							getCurrentTime: () => number;
+							getDuration: () => number;
+						};
+					}) => void,
+				) => void;
+			}
+		).addEventListener('onStateChange', eggsOnYoutubeSongStateChange);
 	}
 }
 
@@ -35,7 +45,7 @@ function eggsToggleExternalPlayer(mutationList: MutationRecord[]) {
 		// external player has been closed
 		if (
 			(removedList[0] as HTMLElement).classList.contains(
-				'fancybox-overlay'
+				'fancybox-overlay',
 			)
 		) {
 			eggsOnYoutubeClose();
@@ -46,7 +56,7 @@ function eggsToggleExternalPlayer(mutationList: MutationRecord[]) {
 
 function eggsReplaceYoutubeVideo() {
 	const videoFrame = document.querySelector(
-		'.fancybox-inner iframe'
+		'.fancybox-inner iframe',
 	) as HTMLIFrameElement;
 	eggsVideoId = videoFrame.src.split('/').pop()?.split('?')[0];
 
@@ -62,7 +72,7 @@ function eggsReplaceYoutubeVideo() {
 		videoFrame.contentWindow &&
 			videoFrame.contentWindow.postMessage(
 				message,
-				'https://www.youtube.com'
+				'https://www.youtube.com',
 			);
 
 		message = JSON.stringify({
@@ -75,7 +85,7 @@ function eggsReplaceYoutubeVideo() {
 		videoFrame.contentWindow &&
 			videoFrame.contentWindow.postMessage(
 				message,
-				'https://www.youtube.com'
+				'https://www.youtube.com',
 			);
 	});
 }
@@ -95,7 +105,7 @@ window.addEventListener('message', (event) => {
 	}
 });
 
-function eggsOnYoutubeStateChange(data: any) {
+function eggsOnYoutubeStateChange(data: { info: number }) {
 	const currentPlayer = document.querySelector(`a[href*="${eggsVideoId}"]`);
 	const parentElmt =
 		(currentPlayer && currentPlayer.closest('li')) || document;
@@ -112,14 +122,14 @@ function eggsOnYoutubeStateChange(data: any) {
 			},
 			trackInfo: {
 				artist: parentElmt.querySelector(
-					`.artist_name${eggsIsArtistPage ? '' : ' a'}`
+					`.artist_name${eggsIsArtistPage ? '' : ' a'}`,
 				)?.textContent,
 				track: parentElmt.querySelector(
-					`.product_name${eggsIsArtistPage ? ' a' : ' p'}`
+					`.product_name${eggsIsArtistPage ? ' a' : ' p'}`,
 				)?.textContent,
 			},
 		},
-		'*'
+		'*',
 	);
 }
 
@@ -138,18 +148,21 @@ function eggsOnYoutubeClose() {
 			},
 			trackInfo: {
 				artist: parentElmt.querySelector(
-					`.artist_name${eggsIsArtistPage ? '' : ' a'}`
+					`.artist_name${eggsIsArtistPage ? '' : ' a'}`,
 				)?.textContent,
 				track: parentElmt.querySelector(
-					`.product_name${eggsIsArtistPage ? ' a' : ' p'}`
+					`.product_name${eggsIsArtistPage ? ' a' : ' p'}`,
 				)?.textContent,
 			},
 		},
-		'*'
+		'*',
 	);
 }
 
-function eggsOnYoutubeSongStateChange(event: any) {
+function eggsOnYoutubeSongStateChange(event: {
+	data: number;
+	target: { getCurrentTime: () => number; getDuration: () => number };
+}) {
 	const currentPlayer = document.querySelector(`a[href*="${eggsVideoId}"]`);
 	const parentElmt =
 		(currentPlayer && currentPlayer.closest('li')) || document;
@@ -166,18 +179,20 @@ function eggsOnYoutubeSongStateChange(event: any) {
 			},
 			trackInfo: {
 				artist: parentElmt.querySelector(
-					`.artist_name${eggsIsArtistPage ? '' : ' a'}`
+					`.artist_name${eggsIsArtistPage ? '' : ' a'}`,
 				)?.textContent,
 				track: parentElmt.querySelector(
-					`.product_name${eggsIsArtistPage ? ' a' : ' p'}`
+					`.product_name${eggsIsArtistPage ? ' a' : ' p'}`,
 				)?.textContent,
 			},
 		},
-		'*'
+		'*',
 	);
 }
 
-function eggsGetTimestamps(data: any) {
+function eggsGetTimestamps(data: {
+	info?: { currentTime?: number; duration?: number };
+}) {
 	if (data.info) {
 		if (data.info.currentTime) {
 			eggsCurrentTime = data.info.currentTime;
diff --git a/src/connectors/eggs.ts b/src/connectors/eggs.ts
index 9a10ed5d..db8ef103 100644
--- a/src/connectors/eggs.ts
+++ b/src/connectors/eggs.ts
@@ -10,7 +10,7 @@ let isPlaying = false;
 
 Connector.getTimeInfo = () => {
 	const { currentTime, duration } = document.querySelector(
-		'#aPlayer'
+		'#aPlayer',
 	) as HTMLAudioElement;
 	return { currentTime, duration };
 };
@@ -83,7 +83,7 @@ function checkToggleArtist(mutationList: MutationRecord[]) {
 		// external player has been closed
 		if (
 			(removedList[0] as HTMLElement).classList.contains(
-				'fancybox-overlay'
+				'fancybox-overlay',
 			)
 		) {
 			setArtistConnector();
@@ -91,8 +91,10 @@ function checkToggleArtist(mutationList: MutationRecord[]) {
 	}
 }
 
-Connector.onScriptEvent = (event: any) => {
-	({ trackInfo, isPlaying, timeInfo } = event.data);
+Connector.onScriptEvent = (event: MessageEvent<Record<string, unknown>>) => {
+	trackInfo = event.data.trackInfo as object;
+	isPlaying = event.data.isPlaying as boolean;
+	timeInfo = event.data.timeInfo as object;
 
 	if (event.data.playerType === 'youtube') {
 		Connector.onStateChanged();
diff --git a/src/connectors/globalplayer.ts b/src/connectors/globalplayer.ts
index 9f03aa39..a9867b6c 100644
--- a/src/connectors/globalplayer.ts
+++ b/src/connectors/globalplayer.ts
@@ -1,14 +1,16 @@
 export {};
 
-const showNameSelector = '.show-info-with-image__text__title';
+const showNameSelector =
+	'div[class^="style_playbarInfo"] div[data-testid="show-info-title"]';
 
-Connector.playerSelector = '.track-container';
-
-Connector.trackSelector = '.track-container .show-info__text__title';
-
-Connector.artistSelector = '.track-container .show-info__text__subtitle';
-
-Connector.playButtonSelector = '.circular-play-button';
+Connector.playerSelector = ".globalplayer";
+Connector.trackSelector =
+	'div[data-testid="show-info-card"] h1[data-testid="show-info-title"]';
+Connector.artistSelector =
+	'div[data-testid="show-info-card"] h2[data-testid="show-info-subtitle"]';
+Connector.playButtonSelector =
+	'button[data-testid="play-pause-button"][aria-pressed="false"]';
+Connector.trackArtSelector = 'div[class^="style_showInfoCard"] img.current-img';
 
 Connector.isScrobblingAllowed = () => {
 	return Connector.getTrack() !== getShowName();
diff --git a/src/connectors/idagio.ts b/src/connectors/idagio.ts
index df0d5552..768db963 100644
--- a/src/connectors/idagio.ts
+++ b/src/connectors/idagio.ts
@@ -23,7 +23,7 @@ Connector.currentTimeSelector = '.player-PlayerProgress__progress--2F0qB>span';
 Connector.durationSelector = '.player-PlayerProgress__timeTotal--3aHlj span';
 
 Connector.isPlaying = () =>
-	Util.getTextFromSelectors(pauseButtonSelector) === 'Pause';
+	Util.getTextFromSelectors(pauseButtonSelector)?.toUpperCase() === 'PAUSE';
 
 Connector.isScrobblingAllowed = () =>
 	Util.getTextFromSelectors('.player-PlayerInfo__recordingInfo--15VMv') !==
diff --git a/src/connectors/iramanusantara.ts b/src/connectors/iramanusantara.ts
index 8cef2d29..1e7cf83f 100644
--- a/src/connectors/iramanusantara.ts
+++ b/src/connectors/iramanusantara.ts
@@ -9,6 +9,14 @@ Connector.trackSelector = '#player-music > div > span:nth-child(1)';
 // Album title is only available when track is played through the album page
 Connector.albumSelector = 'h1:first-of-type';
 
-Connector.playButtonSelector = 'li > div > div:nth-child(2) > button:nth-child(2)';
-
 Connector.trackArtSelector = '#player-music > span > img';
+
+Connector.isPlaying = () => {
+	return (
+		Util.getAttrFromSelectors('#player-control button svg path', 'd') ===
+		'M9 8v6m4-6v6m7-3a9 9 0 11-18 0 9 9 0 0118 0z'
+	);
+};
+
+Connector.currentTimeSelector = '#seek time:nth-of-type(1)';
+Connector.durationSelector = '#seek time:nth-of-type(2)';
diff --git a/src/connectors/musickit-dom-inject.ts b/src/connectors/musickit-dom-inject.ts
index e69e73e4..05f7706e 100644
--- a/src/connectors/musickit-dom-inject.ts
+++ b/src/connectors/musickit-dom-inject.ts
@@ -5,19 +5,48 @@
  */
 musicKitAddEventListeners();
 
+interface MusicKitWindow {
+	MusicKit: {
+		Events: {
+			metadataDidChange: unknown;
+			playbackStateDidChange: unknown;
+			nowPlayingItemDidChange: unknown;
+		};
+		getInstance: () => MusicKitInstance;
+	};
+}
+
+interface MusicKitInstance {
+	player?: MusicKitInstance;
+	addEventListener: (_: unknown, __: () => void) => void;
+	nowPlayingItem: {
+		albumName: string;
+		title: string;
+		artistName: string;
+		artworkURL: string;
+		container?: {
+			attributes?: { [key: string]: string };
+		};
+		id: unknown;
+	};
+	currentPlaybackDuration: number;
+	currentPlaybackTime: number;
+	isPlaying: boolean;
+}
+
 async function musicKitAddEventListeners() {
-	const Events = (window as any).MusicKit.Events;
+	const Events = (window as unknown as MusicKitWindow).MusicKit.Events;
 	const instance = await musicKitInstance();
 	instance.addEventListener(Events.metadataDidChange, musicKitSendEvent);
 	instance.addEventListener(Events.playbackStateDidChange, musicKitSendEvent);
 	instance.addEventListener(
 		Events.nowPlayingItemDidChange,
-		musicKitSendEvent
+		musicKitSendEvent,
 	);
 }
 
 async function musicKitInstance() {
-	const api = (window as any).MusicKit;
+	const api = (window as unknown as MusicKitWindow).MusicKit;
 
 	const initInstance = api?.getInstance();
 	// If the instance is already available, return it immediately
@@ -27,7 +56,7 @@ async function musicKitInstance() {
 
 	// Otherwise, poll until it is available
 	let i = 0;
-	return new Promise<any>((resolve, reject) => {
+	return new Promise<MusicKitInstance>((resolve, reject) => {
 		const interval = setInterval(() => {
 			const instance = api?.getInstance();
 			if (instance) {
@@ -52,7 +81,7 @@ async function musicKitSendEvent() {
 			trackInfo: await musicKitGetTrackInfo(),
 			isPlaying: await musicKitIsPlaying(),
 		},
-		'*'
+		'*',
 	);
 }
 
diff --git a/src/connectors/musickit.ts b/src/connectors/musickit.ts
index d8634b02..c7e96261 100644
--- a/src/connectors/musickit.ts
+++ b/src/connectors/musickit.ts
@@ -14,7 +14,7 @@ Connector.getTrackInfo = () => trackInfo;
 Connector.onScriptEvent = (e) => {
 	switch (e.data.type) {
 		case 'MUSICKIT_STATE':
-			trackInfo = e.data.trackInfo as any;
+			trackInfo = e.data.trackInfo as object;
 			isPlaying = e.data.isPlaying as boolean;
 
 			Connector.onStateChanged();
diff --git a/src/connectors/plex.ts b/src/connectors/plex.ts
index 010302b7..b8ad0ac0 100644
--- a/src/connectors/plex.ts
+++ b/src/connectors/plex.ts
@@ -6,7 +6,12 @@ const plexFilter = MetadataFilter.createFilter({
 	album: removeUnknownAlbum,
 });
 
-Connector.playerSelector = '[class^=Player-miniPlayerContainer]';
+Connector.useMediaSessionApi();
+
+Connector.playerSelector = [
+	'[class^=PlayerContainer-container]',
+    '[class^=Player-miniPlayerContainer]',
+];
 
 Connector.trackSelector = `${titleContainer} a[class*=MetadataPosterTitle]`;
 
diff --git a/src/connectors/poolsuite.ts b/src/connectors/poolsuite.ts
index 5281f819..5444e797 100644
--- a/src/connectors/poolsuite.ts
+++ b/src/connectors/poolsuite.ts
@@ -2,7 +2,9 @@ export {};
 
 Connector.playButtonSelector = '.middle.paused';
 Connector.playerSelector = '.inner-size';
-Connector.trackSelector = '.current-track a:first';
-Connector.artistSelector = '.current-track a:last';
-Connector.currentTimeSelector = '.timer span:first';
-Connector.durationSelector = '.timer span:last';
+Connector.trackSelector = '.current-track h3';
+Connector.artistSelector = '.current-track h2';
+Connector.currentTimeSelector = '.timer span:nth-child(1)';
+Connector.durationSelector = '.timer span:nth-child(2)';
+
+Connector.isScrobblingAllowed = () => Connector.getTrack() !== 'Loading...';
diff --git a/src/connectors/radcap.ts b/src/connectors/radcap.ts
new file mode 100644
index 00000000..c5299d76
--- /dev/null
+++ b/src/connectors/radcap.ts
@@ -0,0 +1,39 @@
+export {};
+
+function setupConnector() {
+  if (isDesktopPlayer()) {
+    setupDesktopPlayer();
+	} 
+  else {
+    setupMobilePlayer();
+	}
+}
+
+function isDesktopPlayer() {
+  return Boolean(document.querySelector('.radio'));
+}
+
+function setupDesktopPlayer() {
+  Connector.playerSelector = '.radio';
+
+  Connector.artistTrackSelector = '.stream.stream-signal > tbody > tr > td';
+
+  Connector.playButtonSelector = '#oframeplayer-d > pjsdiv:nth-child(7)';
+}
+
+function setupMobilePlayer() {
+  Connector.playerSelector = '.container';
+
+  Connector.artistTrackSelector = 'table.stream > tbody > tr > td';
+
+  const upperPlayerPlayButton = '#oframeaudioplayer2 > pjsdiv:nth-child(8) > pjsdiv:nth-child(2)';
+
+  const lowerPlayerPlayButton = '#oframeaudioplayer0 > pjsdiv:nth-child(8) > pjsdiv:nth-child(2)';
+
+  Connector.isPlaying = () => {
+    return (Util.getCSSPropertyFromSelectors(upperPlayerPlayButton, 'visibility') === 'hidden'
+    || Util.getCSSPropertyFromSelectors(lowerPlayerPlayButton, 'visibility') === 'hidden')
+  };
+}
+
+setupConnector();
diff --git a/src/connectors/sber-zvuk-dom-inject.ts b/src/connectors/sber-zvuk-dom-inject.ts
index f9fc3107..212ecf17 100644
--- a/src/connectors/sber-zvuk-dom-inject.ts
+++ b/src/connectors/sber-zvuk-dom-inject.ts
@@ -1,4 +1,19 @@
-function sberGetTrackInfo(track: any, currentTime: number) {
+interface TrackInfo {
+	title: string;
+	credits: string;
+	duration: number;
+	id: string;
+	image: { src: string };
+	release_title: string;
+}
+
+interface QueueEventObject {
+	Queue: QueueEventObject;
+	currentTrack: TrackInfo;
+	Player: { currentTime: number };
+}
+
+function sberGetTrackInfo(track: TrackInfo, currentTime: number) {
 	const { title, credits, duration, id, image, release_title: album } = track;
 	const trackArt = image.src.replace('{size}', '400x400');
 
@@ -13,7 +28,12 @@ function sberGetTrackInfo(track: any, currentTime: number) {
 	};
 }
 
-function sberQueueEvent(event: any) {
+function sberQueueEvent(event: {
+	type: string;
+	name: string;
+	newValue: unknown;
+	object: QueueEventObject;
+}) {
 	let type = null;
 	let queue;
 
@@ -40,7 +60,7 @@ function sberQueueEvent(event: any) {
 
 	const trackInfo = sberGetTrackInfo(
 		queue.currentTrack,
-		queue.Player.currentTime
+		queue.Player.currentTime,
 	);
 
 	window.postMessage(
@@ -49,12 +69,16 @@ function sberQueueEvent(event: any) {
 			type,
 			trackInfo,
 		},
-		'*'
+		'*',
 	);
 }
 
 function sberSetupEventListeners() {
-	(window as any).newPlayer.$mobx.observe(sberQueueEvent);
+	(
+		window as unknown as {
+			newPlayer: { $mobx: { observe: (ev: object) => void } };
+		}
+	).newPlayer.$mobx.observe(sberQueueEvent);
 }
 
 sberSetupEventListeners();
diff --git a/src/connectors/sber-zvuk.ts b/src/connectors/sber-zvuk.ts
index 990d352b..044db261 100644
--- a/src/connectors/sber-zvuk.ts
+++ b/src/connectors/sber-zvuk.ts
@@ -17,7 +17,7 @@ Connector.onScriptEvent = (event) => {
 			break;
 	}
 
-	trackInfo = event.data.trackInfo as any;
+	trackInfo = event.data.trackInfo as object;
 
 	Connector.onStateChanged();
 };
diff --git a/src/connectors/siriusxm-player.ts b/src/connectors/siriusxm-player.ts
index 1fc02c10..b79484f1 100644
--- a/src/connectors/siriusxm-player.ts
+++ b/src/connectors/siriusxm-player.ts
@@ -10,34 +10,48 @@ export {};
 const filter = MetadataFilter.createFilter({ track: removeYear });
 const removeYearRe = /\s\(\d{2}\)\s?$/g;
 
-Connector.playerSelector = '.sxm-player-controls';
-
-Connector.artistSelector = '.sxm-player-controls .artist-name';
-
-Connector.trackSelector = '.sxm-player-controls .track-name';
+Connector.playerSelector = ".sxm-player-controls";
+Connector.artistSelector = ".sxm-player-controls .artist-name";
+Connector.trackSelector = ".sxm-player-controls .track-name";
 
 Connector.isPlaying = () => {
 	return (
 		Util.getAttrFromSelectors(
-			'.sxm-player-controls .play-pause-btn',
-			'title'
-		) === 'Pause'
+			".sxm-player-controls .play-pause-btn",
+			"title"
+		) === "Pause"
 	);
 };
 
-Connector.trackArtSelector = '.album-image-cell img';
+Connector.trackArtSelector = ".album-image-cell img.album-image";
 
 Connector.isScrobblingAllowed = () => {
-	const artist = Connector.getArtist();
-	if (artist) {
-		return !artist.toLowerCase().includes('siriusxmu');
-	}
-
-	return false;
+	const artist = Connector.getArtist()?.toLowerCase();
+	const track = Connector.getTrack()?.toLowerCase();
+	const filteredTerms = [
+		"@siriusxm",
+		"@jennylsq",
+		"@radiomadison",
+		"@morningmashup",
+		"josiah",
+		"1-877-33-sirius",
+		"@sxm", //will broadly catch a bunch of sxm Twitter handles
+		"altnation",
+		".ca",
+		".com",
+		"indie 1.0",
+		"#",
+		"facebook",
+		"twitter",
+	];
+
+	return !filteredTerms.some(
+		(term) => artist?.includes(term) || track?.includes(term)
+	);
 };
 
 Connector.applyFilter(filter);
 
 function removeYear(track: string) {
-	return track.replace(removeYearRe, '');
+	return track.replace(removeYearRe, "");
 }
diff --git a/src/connectors/synology.ts b/src/connectors/synology.ts
index 6b34708d..d5cb3aec 100644
--- a/src/connectors/synology.ts
+++ b/src/connectors/synology.ts
@@ -7,7 +7,17 @@ Connector.trackSelector = '.info-title';
 Connector.getTrackInfo = () => {
 	const albumArtistText =
 		document.querySelector('.info-album-artist')?.textContent;
-	return Util.splitArtistAlbum(albumArtistText, null, true);
+
+	if (!albumArtistText) {
+		return {};
+	}
+
+	const album = albumArtistText.substr(0, albumArtistText.lastIndexOf(' - '));
+	const artist = albumArtistText.substr(
+		albumArtistText.lastIndexOf(' - ') + 3
+	);
+
+	return { artist, album };
 };
 
 Connector.currentTimeSelector = '.info-position';
diff --git a/src/connectors/tidal.ts b/src/connectors/tidal.ts
index 103f2af2..8bd465f5 100644
--- a/src/connectors/tidal.ts
+++ b/src/connectors/tidal.ts
@@ -25,7 +25,12 @@ Connector.getUniqueID = () => {
 	return null;
 };
 
-Connector.artistSelector = `${Connector.playerSelector} span.artist-link`;
+const artistSelector = `${Connector.playerSelector} span.artist-link a`;
+
+Connector.getArtist = () => {
+	const artistNodes = document.querySelectorAll(artistSelector);
+	return Util.joinArtists(Array.from(artistNodes));
+};
 
 Connector.albumSelector = [
 	'#nowPlaying div.react-tabs a[href^="/album/"]',
@@ -39,7 +44,8 @@ Connector.getAlbumArtist = () => {
 		'href'
 	);
 	if (albumUrl && canonicalUrl && canonicalUrl.endsWith(albumUrl)) {
-		return Util.getTextFromSelectors('#main .header-details .artist-link');
+		const albumArtistNode = document.querySelectorAll('#main .header-details .artist-link a');
+		return Util.joinArtists(Array.from(albumArtistNode));
 	}
 	return null;
 };
diff --git a/src/connectors/trackerhub.ts b/src/connectors/trackerhub.ts
new file mode 100644
index 00000000..d312091e
--- /dev/null
+++ b/src/connectors/trackerhub.ts
@@ -0,0 +1,4 @@
+export {};
+
+Connector.useMediaSessionApi();
+Connector.playerSelector = '#player';
diff --git a/src/connectors/vk-dom-inject.ts b/src/connectors/vk-dom-inject.ts
index 16b9024e..be93500f 100644
--- a/src/connectors/vk-dom-inject.ts
+++ b/src/connectors/vk-dom-inject.ts
@@ -13,14 +13,24 @@ const VK_INFO_ADDITIONAL = 16;
 
 vkSetupEventListeners();
 
+interface VKWindow {
+	ap: {
+		_currentAudio?: string[];
+		_impl: { _currentAudioEl?: { currentTime: string } };
+		subscribers: {
+			push: (_: object) => void;
+		};
+	};
+}
+
 function vkSendUpdateEvent(type: string) {
-	const audioObject = (window as any).ap._currentAudio;
+	const audioObject = (window as unknown as VKWindow).ap._currentAudio;
 	if (!audioObject) {
 		return;
 	}
 
-	const audioElImpl = (window as any).ap._impl._currentAudioEl || {};
-	const { currentTime } = audioElImpl;
+	const currentTime = (window as unknown as VKWindow).ap._impl._currentAudioEl
+		?.currentTime;
 
 	/*
 	 * VK player sets current time equal to song duration on startup.
@@ -52,13 +62,13 @@ function vkSendUpdateEvent(type: string) {
 				artist: audioObject[VK_INFO_ARTIST],
 			},
 		},
-		'*'
+		'*',
 	);
 }
 
 function vkSetupEventListeners() {
 	for (const e of ['start', 'progress', 'pause', 'stop']) {
-		(window as any).ap.subscribers.push({
+		(window as unknown as VKWindow).ap.subscribers.push({
 			et: e,
 			cb: vkSendUpdateEvent.bind(null, e),
 		});
diff --git a/src/connectors/vk.ts b/src/connectors/vk.ts
index e9975356..3f4e0a4b 100644
--- a/src/connectors/vk.ts
+++ b/src/connectors/vk.ts
@@ -6,8 +6,8 @@ let isPlaying = false;
 const vkFilter = MetadataFilter.createFilter(
 	MetadataFilter.createFilterSetForFields(
 		['artist', 'track', 'album', 'albumArtist'],
-		MetadataFilter.decodeHtmlEntities
-	)
+		MetadataFilter.decodeHtmlEntities,
+	),
 ).extend(MetadataFilter.createRemasteredFilter());
 
 Connector.isPlaying = () => isPlaying;
@@ -25,7 +25,7 @@ Connector.onScriptEvent = (event) => {
 			break;
 	}
 
-	trackInfo = event.data.trackInfo as any;
+	trackInfo = event.data.trackInfo as object;
 
 	Connector.onStateChanged();
 };
diff --git a/src/connectors/yandex-music-dom-inject.ts b/src/connectors/yandex-music-dom-inject.ts
index 06810ffc..b89729b1 100644
--- a/src/connectors/yandex-music-dom-inject.ts
+++ b/src/connectors/yandex-music-dom-inject.ts
@@ -1,4 +1,22 @@
-const YandexAPI = (window as any).externalAPI;
+interface YandexWindow {
+	externalAPI: {
+		on: (_: unknown, __: () => void) => void;
+		EVENT_STATE: unknown;
+		EVENT_TRACK: unknown;
+		isPlaying: () => boolean;
+		getCurrentTrack: () => {
+			title: string;
+			album: { title: string };
+			cover: string;
+			artists: { title: string }[];
+			duration: number;
+			link: string;
+		};
+		getProgress: () => { position: number };
+	};
+}
+
+const YandexAPI = (window as unknown as YandexWindow).externalAPI;
 
 yandexSetupListeners();
 
@@ -15,7 +33,7 @@ function yandexOnEvent() {
 			trackInfo: yandexGetTrackInfo(),
 			isPlaying: YandexAPI.isPlaying(),
 		},
-		'*'
+		'*',
 	);
 }
 
diff --git a/src/connectors/yandex-music.ts b/src/connectors/yandex-music.ts
index d3865739..42e84c7b 100644
--- a/src/connectors/yandex-music.ts
+++ b/src/connectors/yandex-music.ts
@@ -10,7 +10,7 @@ Connector.getTrackInfo = () => trackInfo;
 Connector.onScriptEvent = (e) => {
 	switch (e.data.type) {
 		case 'YANDEX_MUSIC_STATE':
-			trackInfo = e.data.trackInfo as any;
+			trackInfo = e.data.trackInfo as object;
 			isPlaying = e.data.isPlaying as boolean;
 
 			Connector.onStateChanged();
diff --git a/src/connectors/youtube.ts b/src/connectors/youtube.ts
index ac62daf0..6688a736 100644
--- a/src/connectors/youtube.ts
+++ b/src/connectors/youtube.ts
@@ -65,7 +65,14 @@ let getTrackInfoFromYtMusicEnabled = false;
 let currentVideoDescription: string | null = null;
 let artistTrackFromDescription: TrackInfoWithAlbum | null = null;
 
-const getTrackInfoFromYoutubeMusicCache: any = {};
+const getTrackInfoFromYoutubeMusicCache: {
+	[videoId: string]: {
+		done?: boolean;
+		recognisedByYtMusic?: boolean;
+		videoId?: string | null;
+		currentTrackInfo?: { artist?: string; track?: string };
+	};
+} = {};
 
 const trackInfoGetters = [
 	getTrackInfoFromChapters,
@@ -117,7 +124,7 @@ Connector.getTrackInfo = () => {
 
 Connector.getTimeInfo = () => {
 	const videoElement = document.querySelector(
-		videoSelector
+		videoSelector,
 	) as HTMLVideoElement;
 	if (videoElement && !areChaptersAvailable()) {
 		let { currentTime, duration, playbackRate } = videoElement;
@@ -187,7 +194,7 @@ Connector.applyFilter(
 	MetadataFilter.createYouTubeFilter().append({
 		artist: [removeLtrRtlChars, removeNumericPrefix],
 		track: [removeLtrRtlChars, removeNumericPrefix],
-	})
+	}),
 );
 
 function setupEventListener() {
@@ -202,7 +209,7 @@ function areChaptersAvailable() {
 	// SponsorBlock extension hijacks chapter element. Ignore it.
 	if (
 		document.querySelector(
-			'.ytp-chapter-title-content.sponsorBlock-segment-title'
+			'.ytp-chapter-title-content.sponsorBlock-segment-title',
 		)
 	) {
 		return false;
@@ -220,7 +227,7 @@ function getVideoId() {
 	 */
 	const miniPlayerVideoUrl = Util.getAttrFromSelectors(
 		'ytd-miniplayer[active] [selected] a',
-		'href'
+		'href',
 	);
 	if (miniPlayerVideoUrl) {
 		return Util.getYtVideoIdFromUrl(miniPlayerVideoUrl);
@@ -228,7 +235,7 @@ function getVideoId() {
 
 	const videoIDDesktop = Util.getAttrFromSelectors(
 		'ytd-watch-flexy',
-		'video-id'
+		'video-id',
 	);
 	if (videoIDDesktop) {
 		return videoIDDesktop;
@@ -264,7 +271,7 @@ function getVideoCategory() {
 		.catch((err) => {
 			Util.debugLog(
 				`Failed to fetch category for ${videoId}: ${err}`,
-				'warn'
+				'warn',
 			);
 			categoryCache.set(videoId, categoryUnknown);
 		});
@@ -399,7 +406,7 @@ function getTrackInfoFromYoutubeMusic() {
 				done: true,
 				recognisedByYtMusic:
 					videoInfo.videoDetails?.musicVideoType?.startsWith(
-						'MUSIC_VIDEO_'
+						'MUSIC_VIDEO_',
 					) || false,
 			};
 
@@ -421,7 +428,7 @@ function getTrackInfoFromYoutubeMusic() {
 		.catch((err) => {
 			Util.debugLog(
 				`Failed to fetch youtube music data for ${videoId}: ${err}`,
-				'warn'
+				'warn',
 			);
 			getTrackInfoFromYoutubeMusicCache[videoId ?? ''] = {
 				done: true,
@@ -449,7 +456,7 @@ function getTrackInfoFromChapters() {
 
 function getTrackInfoFromTitle() {
 	let { artist, track } = Util.processYtVideoTitle(
-		Util.getTextFromSelectors(videoTitleSelector)
+		Util.getTextFromSelectors(videoTitleSelector),
 	);
 	if (!artist) {
 		artist = Util.getTextFromSelectors(channelNameSelector);
@@ -480,7 +487,7 @@ function removeNumericPrefix(text: string) {
 
 function isVideoStartedPlaying() {
 	const videoElement = document.querySelector(
-		videoSelector
+		videoSelector,
 	) as HTMLVideoElement;
 	return videoElement && videoElement.currentTime > 0;
 }
diff --git a/src/core/connectors.ts b/src/core/connectors.ts
index e4a24d7b..41f919ae 100644
--- a/src/core/connectors.ts
+++ b/src/core/connectors.ts
@@ -2100,4 +2100,16 @@ export default <ConnectorMeta[]>[
 		js: 'fungjai.js',
 		id: 'fungjai',
 	},
+	{
+		label: 'Radio Caprice',
+		matches: ['*://radcap.ru/*'],
+		js: 'radcap.js',
+		id: 'radcap',
+	},
+	{
+		label: 'TrackerHub',
+		matches: ['*://trackerhub.vercel.app/*'],
+		js: 'trackerhub.js',
+		id: 'trackerhub',
+	},
 ];
diff --git a/src/core/content/util.ts b/src/core/content/util.ts
index 77bd2514..cba5a511 100644
--- a/src/core/content/util.ts
+++ b/src/core/content/util.ts
@@ -101,7 +101,7 @@ export function stringToSeconds(str: string | null | undefined): number {
  */
 export function findSeparator(
 	str: string | null,
-	separators: Separator[] | null = null
+	separators: Separator[] | null = null,
 ): { index: number; length: number } | null {
 	if (str === null || str.length === 0) {
 		return null;
@@ -145,7 +145,7 @@ export function joinArtists(artists: Node[]): string | null {
 export function splitArtistTrack(
 	str: string | null | undefined,
 	separators: Separator[] | null = null,
-	swap = false
+	swap = false,
 ): ArtistTrackInfo {
 	if (!str) {
 		return { artist: null, track: null };
@@ -181,7 +181,7 @@ export function removeRecordSide(str: string | null): string | null {
 export function splitArtistAlbum(
 	str: string | null | undefined,
 	separators: Separator[] | null = null,
-	swap = false
+	swap = false,
 ): { artist: string | null; album: string | null } {
 	const [artist, album] = splitString(str, separators, swap);
 	return { artist, album };
@@ -197,7 +197,7 @@ export function splitArtistAlbum(
 export function splitTimeInfo(
 	str: string | null,
 	separator: Separator = '/',
-	swap = false
+	swap = false,
 ): TimeInfo {
 	if (str === null) {
 		return {
@@ -206,7 +206,7 @@ export function splitTimeInfo(
 		};
 	}
 	const [currentTime, duration] = splitString(str, [separator], swap).map(
-		(e) => stringToSeconds(e)
+		(e) => stringToSeconds(e),
 	);
 
 	return { currentTime, duration };
@@ -222,7 +222,7 @@ export function splitTimeInfo(
 export function splitString(
 	str: string | null | undefined,
 	separators: Separator[] | null,
-	swap = false
+	swap = false,
 ): [string | null, string | null] {
 	let first = null;
 	let second = null;
@@ -265,7 +265,7 @@ export function escapeBadTimeValues(time: unknown): number | null {
  * @returns Track art URL
  */
 export function extractUrlFromCssProperty(
-	cssProperty: string | null | undefined
+	cssProperty: string | null | undefined,
 ): string | null {
 	if (!cssProperty) {
 		return null;
@@ -313,7 +313,7 @@ export function throttle<T>(func: () => T, wait: number): () => T | undefined {
  * @returns True if object is empty; false otherwise
  */
 export function isArtistTrackEmpty(
-	artistTrack: ArtistTrackInfo | null
+	artistTrack: ArtistTrackInfo | null,
 ): boolean {
 	return !(artistTrack && artistTrack.artist && artistTrack.track);
 }
@@ -329,7 +329,7 @@ export function isArtistTrackEmpty(
 export function fillEmptyFields(
 	target: State,
 	source: State | null | undefined,
-	fields: (keyof State)[] | undefined
+	fields: (keyof State)[] | undefined,
 ): State {
 	if (!source || !Array.isArray(fields)) {
 		return target;
@@ -352,7 +352,7 @@ export function fillEmptyFields(
  * @returns Track info
  */
 export function getMediaSessionInfo(
-	mediaSession: MediaSession
+	mediaSession: MediaSession,
 ): BaseState | null {
 	if (!(mediaSession && mediaSession.metadata)) {
 		return null;
@@ -383,7 +383,7 @@ export function getMediaSessionInfo(
 /* istanbul ignore next */
 export function getTextFromSelectors(
 	selectors: string | string[] | null,
-	defaultValue: string | null = null
+	defaultValue: string | null = null,
 ): string | null {
 	if (selectors === null) {
 		return defaultValue;
@@ -419,7 +419,7 @@ export function getTextFromSelectors(
 export function getAttrFromSelectors(
 	selectors: string | string[] | null,
 	attr: string,
-	defaultValue: string | null = null
+	defaultValue: string | null = null,
 ): string | null {
 	if (selectors === null) {
 		return defaultValue;
@@ -452,7 +452,7 @@ export function getAttrFromSelectors(
 export function bindListeners(
 	selectors: string | string[],
 	events: string | string[],
-	fn: (e: Event) => void
+	fn: (e: Event) => void,
 ) {
 	const elements = queryElements(selectors);
 	if (!elements) {
@@ -478,7 +478,7 @@ export function bindListeners(
  */
 /* istanbul ignore next */
 export function getSecondsFromSelectors(
-	selectors: string | string[] | null
+	selectors: string | string[] | null,
 ): number | undefined {
 	return stringToSeconds(getTextFromSelectors(selectors) ?? '');
 }
@@ -490,7 +490,7 @@ export function getSecondsFromSelectors(
  */
 /* istanbul ignore next */
 export function extractImageUrlFromSelectors(
-	selectors: string | string[] | null
+	selectors: string | string[] | null,
 ): string | null {
 	if (selectors === null) {
 		return null;
@@ -524,7 +524,7 @@ export function extractImageUrlFromSelectors(
  */
 export function getCSSPropertyFromSelectors(
 	selectors: string | string[],
-	property: string
+	property: string,
 ) {
 	const elements = queryElements(selectors);
 	if (!elements) {
@@ -557,7 +557,7 @@ export function getCSSProperty(element: Element, property: string) {
 /* istanbul ignore next */
 export function hasElementClass(
 	selectors: string | string[] | null,
-	cls: string
+	cls: string,
 ): boolean {
 	if (selectors === null) {
 		return false;
@@ -601,7 +601,7 @@ function visibleFilter(elements: NodeListOf<HTMLElement>) {
  */
 /* istanbul ignore next */
 export function isElementVisible(
-	selectors: string | string[] | null | undefined
+	selectors: string | string[] | null | undefined,
 ): boolean {
 	if (!selectors) {
 		return false;
@@ -617,7 +617,7 @@ export function isElementVisible(
  * @returns Value, or null if not found
  */
 export function getValueFromSelectors(
-	selectors: string | string[]
+	selectors: string | string[],
 ): string | null {
 	const element = queryElements(selectors);
 	if (!element || !('value' in element)) {
@@ -635,7 +635,7 @@ export function getValueFromSelectors(
  */
 export function getDataFromSelectors(
 	selectors: string | string[],
-	name: string
+	name: string,
 ): string | null {
 	return getAttrFromSelectors(selectors, `data-${name}`);
 }
@@ -649,7 +649,7 @@ export function getDataFromSelectors(
  */
 /* istanbul ignore next */
 export function queryElements(
-	selectors: string | string[] | null | undefined
+	selectors: string | string[] | null | undefined,
 ): NodeListOf<HTMLElement> | null {
 	if (!selectors) {
 		return null;
@@ -665,7 +665,7 @@ export function queryElements(
 
 	for (const selector of selectors) {
 		const elements = document.querySelectorAll(
-			selector
+			selector,
 		) as NodeListOf<HTMLElement>;
 		if (elements.length > 0) {
 			return elements;
@@ -684,7 +684,7 @@ export function queryElements(
 /* istanbul ignore next */
 export async function getOption(
 	connector: string,
-	key: string
+	key: string,
 ): Promise<boolean> {
 	const awaitedStorage = await BrowserStorage;
 	const data = await awaitedStorage
@@ -747,7 +747,7 @@ export function injectScriptIntoDocument(scriptUrl: string): void {
  * @param logType - Log type
  */
 /* istanbul ignore next */
-export function debugLog(text: any, logType: DebugLogType = 'log'): void {
+export function debugLog(text: unknown, logType: DebugLogType = 'log'): void {
 	const logFunc = console[logType];
 
 	if (typeof logFunc !== 'function') {
@@ -797,7 +797,7 @@ export const ytTitleRegExps = [
  * @returns Object containing artist and track fields
  */
 export function processYtVideoTitle(
-	videoTitle: string | null | undefined
+	videoTitle: string | null | undefined,
 ): ArtistTrackInfo {
 	let artist = null;
 	let track = null;
@@ -861,12 +861,12 @@ export function processYtVideoTitle(
 export function isYtVideoDescriptionValid(desc: string | null): desc is string {
 	return Boolean(
 		desc &&
-			(desc.startsWith(ytDescFirstLine) || desc.endsWith(ytDescLastLine))
+			(desc.startsWith(ytDescFirstLine) || desc.endsWith(ytDescLastLine)),
 	);
 }
 
 export function parseYtVideoDescription(
-	desc: string | null
+	desc: string | null,
 ): TrackInfoWithAlbum | null {
 	if (!isYtVideoDescriptionValid(desc)) {
 		return null;
@@ -899,8 +899,8 @@ export function parseYtVideoDescription(
 	} else {
 		[track, artist, ...featArtists] = trackInfo;
 
-		const areFeatArtistPresent = featArtists.some((artist) =>
-			track?.includes(artist)
+		const areFeatArtistPresent = featArtists.some(
+			(artist) => track?.includes(artist),
 		);
 		if (!areFeatArtistPresent) {
 			const featArtistsStr = featArtists.join(ARTIST_SEPARATOR);
@@ -942,7 +942,7 @@ export const scArtistTrackRe = /(.+)\s[:\u2013-\u2015-]\s(.+)/;
  * @returns Object contains artist and track fields
  */
 export function processSoundCloudTrack(
-	track: string | null | undefined
+	track: string | null | undefined,
 ): ArtistTrackInfo {
 	if (!track) {
 		return { artist: null, track: null };
diff --git a/src/types/declaration.d.ts b/src/types/declaration.d.ts
index d834a6c6..62207cb0 100644
--- a/src/types/declaration.d.ts
+++ b/src/types/declaration.d.ts
@@ -4,6 +4,7 @@ declare module '*.scss' {
 }
 
 declare module '*.svg' {
+	// eslint-disable-next-line @typescript-eslint/no-explicit-any
 	const content: any;
 	export default content;
 }
diff --git a/src/ui/popup/popup.module.scss b/src/ui/popup/popup.module.scss
index 91e7ff2d..de7ba615 100644
--- a/src/ui/popup/popup.module.scss
+++ b/src/ui/popup/popup.module.scss
@@ -83,13 +83,14 @@ a {
 		gap: 0.25em;
 		max-width: 50ch;
 		min-width: 30ch;
+		overflow: hidden;
 		padding: 0.5em 1em;
+		text-overflow: ellipsis;
 		white-space: nowrap;
 
 		a {
-			overflow: hidden;
-			text-overflow: ellipsis;
 			white-space: nowrap;
+			width: fit-content;
 		}
 
 		@supports (-webkit-touch-callout: none) {
diff --git a/src/util/communication.ts b/src/util/communication.ts
index a424059c..1cf66619 100644
--- a/src/util/communication.ts
+++ b/src/util/communication.ts
@@ -140,23 +140,23 @@ interface SpecificContentListener<K extends keyof BackgroundCommunications> {
 	type: K;
 	fn: (
 		payload: BackgroundCommunications[K]['payload'],
-		sender: browser.Runtime.MessageSender
+		sender: browser.Runtime.MessageSender,
 	) => BackgroundCommunications[K]['response'];
 }
 
 type ContentListener = <R>(
 	cont: <T extends keyof BackgroundCommunications>(
-		prop: SpecificContentListener<T>
-	) => R
+		prop: SpecificContentListener<T>,
+	) => R,
 ) => R;
 
 export function contentListener<T extends keyof BackgroundCommunications>(
-	property: SpecificContentListener<T>
+	property: SpecificContentListener<T>,
 ): ContentListener {
 	return <R>(
 		cont: <T extends keyof BackgroundCommunications>(
-			prop: SpecificContentListener<T>
-		) => R
+			prop: SpecificContentListener<T>,
+		) => R,
 	) => cont(property);
 }
 
@@ -167,6 +167,7 @@ interface BackgroundMessage<K extends keyof BackgroundCommunications> {
 
 export function setupContentListeners(...listeners: ContentListener[]) {
 	browser.runtime.onMessage.addListener(
+		// eslint-disable-next-line @typescript-eslint/no-explicit-any
 		(message: BackgroundMessage<any>, sender) => {
 			let done = false;
 			for (const l of listeners) {
@@ -181,15 +182,15 @@ export function setupContentListeners(...listeners: ContentListener[]) {
 					return Promise.resolve(response);
 				}
 			}
-		}
+		},
 	);
 }
 
 export async function sendBackgroundMessage<
-	K extends keyof BackgroundCommunications
+	K extends keyof BackgroundCommunications,
 >(
 	tabId: number,
-	message: BackgroundMessage<K>
+	message: BackgroundMessage<K>,
 ): Promise<BackgroundCommunications[K]['response']> {
 	return browser.tabs.sendMessage(tabId, message);
 }
@@ -202,23 +203,23 @@ interface SpecificBackgroundListener<K extends keyof ContentCommunications> {
 	type: K;
 	fn: (
 		payload: ContentCommunications[K]['payload'],
-		sender: browser.Runtime.MessageSender
+		sender: browser.Runtime.MessageSender,
 	) => ContentCommunications[K]['response'];
 }
 
 type BackgroundListener = <R>(
 	cont: <T extends keyof ContentCommunications>(
-		prop: SpecificBackgroundListener<T>
-	) => R
+		prop: SpecificBackgroundListener<T>,
+	) => R,
 ) => R;
 
 export function backgroundListener<T extends keyof ContentCommunications>(
-	property: SpecificBackgroundListener<T>
+	property: SpecificBackgroundListener<T>,
 ): BackgroundListener {
 	return <R>(
 		cont: <T extends keyof ContentCommunications>(
-			prop: SpecificBackgroundListener<T>
-		) => R
+			prop: SpecificBackgroundListener<T>,
+		) => R,
 	) => cont(property);
 }
 
@@ -229,6 +230,7 @@ interface ContentMessage<K extends keyof ContentCommunications> {
 
 export function setupBackgroundListeners(...listeners: BackgroundListener[]) {
 	browser.runtime.onMessage.addListener(
+		// eslint-disable-next-line @typescript-eslint/no-explicit-any
 		(message: ContentMessage<any>, sender) => {
 			let done = false;
 			for (const l of listeners) {
@@ -243,12 +245,12 @@ export function setupBackgroundListeners(...listeners: BackgroundListener[]) {
 					return Promise.resolve(response);
 				}
 			}
-		}
+		},
 	);
 }
 
 export async function sendContentMessage<K extends keyof ContentCommunications>(
-	message: ContentMessage<K>
+	message: ContentMessage<K>,
 ): Promise<ContentCommunications[K]['response']> {
 	return browser.runtime.sendMessage(message);
 }
@@ -261,23 +263,23 @@ interface SpecificPopupListener<K extends keyof PopupCommunications> {
 	type: K;
 	fn: (
 		payload: PopupCommunications[K]['payload'],
-		sender: browser.Runtime.MessageSender
+		sender: browser.Runtime.MessageSender,
 	) => PopupCommunications[K]['response'];
 }
 
 type PopupListener = <R>(
 	cont: <T extends keyof PopupCommunications>(
-		prop: SpecificPopupListener<T>
-	) => R
+		prop: SpecificPopupListener<T>,
+	) => R,
 ) => R;
 
 export function popupListener<T extends keyof PopupCommunications>(
-	property: SpecificPopupListener<T>
+	property: SpecificPopupListener<T>,
 ): PopupListener {
 	return <R>(
 		cont: <T extends keyof PopupCommunications>(
-			prop: SpecificPopupListener<T>
-		) => R
+			prop: SpecificPopupListener<T>,
+		) => R,
 	) => cont(property);
 }
 
@@ -288,6 +290,7 @@ interface PopupMessage<K extends keyof PopupCommunications> {
 
 export function setupPopupListeners(...listeners: PopupListener[]) {
 	browser.runtime.onMessage.addListener(
+		// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Set regardless of previous state
 		(message: PopupMessage<any>, sender) => {
 			let done = false;
 			for (const l of listeners) {
@@ -302,12 +305,12 @@ export function setupPopupListeners(...listeners: PopupListener[]) {
 					return Promise.resolve(response);
 				}
 			}
-		}
+		},
 	);
 }
 
 export async function sendPopupMessage<K extends keyof PopupCommunications>(
-	message: PopupMessage<K>
+	message: PopupMessage<K>,
 ): Promise<PopupCommunications[K]['response']> {
 	return browser.runtime.sendMessage(message);
 }
diff --git a/src/util/emitter.ts b/src/util/emitter.ts
index 008de0e0..980a734a 100644
--- a/src/util/emitter.ts
+++ b/src/util/emitter.ts
@@ -2,7 +2,8 @@
  * Class that emulates event emitter behavior while having strict typing
  */
 export default class EventEmitter<
-	T extends Record<string, (...args: any[]) => void>
+	// eslint-disable-next-line @typescript-eslint/no-explicit-any
+	T extends Record<string, (...args: any[]) => void>,
 > {
 	private events: Map<keyof T, T[keyof T][]> = new Map();
 	/**
@@ -26,7 +27,7 @@ export default class EventEmitter<
 		const curEvents = this.events.get(event) || [];
 		this.events.set(
 			event,
-			curEvents.filter((e) => e !== fn)
+			curEvents.filter((e) => e !== fn),
 		);
 	}
 
diff --git a/src/util/regex.ts b/src/util/regex.ts
index c38cb887..36edb784 100644
--- a/src/util/regex.ts
+++ b/src/util/regex.ts
@@ -1,4 +1,3 @@
-import ClonedSong from '@/core/object/cloned-song';
 import Song, { BaseSong } from '@/core/object/song';
 import * as BrowserStorage from '@/core/storage/browser-storage';
 
@@ -107,7 +106,7 @@ export function searchMatches(search: string | null, text: string): boolean {
 function replaceField(
 	search: string | null,
 	replace: string | null,
-	text: string
+	text: string,
 ): string {
 	if (search === null || replace === null) {
 		return text;
@@ -131,7 +130,7 @@ function replaceField(
 export function replaceFields(
 	search: RegexFields,
 	replace: RegexFields,
-	fields: EditedFields
+	fields: EditedFields,
 ): EditedFields {
 	for (const _field of Object.keys(fields)) {
 		const field = _field as FieldType;
@@ -144,7 +143,7 @@ export function replaceFields(
 		fields[field] = replaceField(
 			search[field],
 			replace[field],
-			fields[field]
+			fields[field],
 		);
 	}
 	return fields;
@@ -191,7 +190,7 @@ export function editSong(edit: RegexEdit, song: Song) {
 	const fields = replaceFields(
 		edit.search,
 		edit.replace,
-		getProcessedFields(song)
+		getProcessedFields(song),
 	);
 
 	for (const [_key, field] of Object.entries(fields)) {
@@ -234,7 +233,7 @@ export function getSongField(clonedSong: BaseSong, type: FieldType): string {
  */
 export function getSongFieldNoRegex(
 	clonedSong: BaseSong,
-	type: FieldType
+	type: FieldType,
 ): string {
 	return (clonedSong.noRegex[type] || clonedSong.parsed[type]) ?? '';
 }


Test patch:
diff --git a/tests/background/song.test.ts b/tests/background/song.test.ts
index 0ebcc36e..9808c3a2 100644
--- a/tests/background/song.test.ts
+++ b/tests/background/song.test.ts
@@ -61,7 +61,7 @@ const DUMMY_CONNECTOR = {
  */
 function createSong(
 	parsedData: ParsedSongData,
-	processedData?: ProcessedSongData
+	processedData?: ProcessedSongData,
 ) {
 	const parsedDataCopy: ParsedSongData = {};
 	for (const prop in defaultParsedData) {
@@ -143,7 +143,7 @@ function testGetDuration() {
 	it('should return parsed duration if no processed duration', () => {
 		const song = createSong(
 			{ duration: parsedDuration },
-			{ duration: processedDuration }
+			{ duration: processedDuration },
 		);
 		expect(song.getDuration()).equals(parsedDuration);
 	});
@@ -378,11 +378,11 @@ function testEquals() {
 	});
 
 	it('should not equal null value', () => {
-		expect(songWithUniqueId.equals(null as any)).to.be.false;
+		expect(songWithUniqueId.equals(null)).to.be.false;
 	});
 
 	it('should not equal non-song object', () => {
-		expect(songWithUniqueId.equals(23 as any)).to.be.false;
+		expect(songWithUniqueId.equals(23)).to.be.false;
 	});
 }
 
diff --git a/tests/background/util.test.ts b/tests/background/util.test.ts
index b42d1523..059830d9 100644
--- a/tests/background/util.test.ts
+++ b/tests/background/util.test.ts
@@ -226,7 +226,7 @@ function runTests() {
 function testDebugLog() {
 	it('should throw an error if type is invalid', () => {
 		function callInvalidDebugLog() {
-			Util.debugLog('Test', 'invalid_type123' as any);
+			Util.debugLog('Test', 'invalid_type123');
 		}
 
 		expect(callInvalidDebugLog).to.throw();
@@ -271,7 +271,10 @@ function testTimeoutPromise() {
  * @param func - Function to be tested
  * @param testData - Array of test data
  */
-function testFunction(func: (...args: any[]) => unknown, testData: TestData[]) {
+function testFunction(
+	func: (...args: unknown[]) => unknown,
+	testData: TestData[],
+) {
 	const boundFunc = func.bind(Util);
 
 	for (const data of testData) {
diff --git a/tests/content/util.test.ts b/tests/content/util.test.ts
index a6404a51..3ce7f645 100644
--- a/tests/content/util.test.ts
+++ b/tests/content/util.test.ts
@@ -2,7 +2,7 @@ import { TestData } from '#/types/types';
 import { expect, it, describe } from 'vitest';
 
 // trick webextension polyfill into thinking this is running in the browser
-(globalThis as any).chrome = {
+(globalThis as { chrome: unknown }).chrome = {
 	runtime: {
 		id: 'mock',
 	},
@@ -1098,7 +1098,10 @@ const testData = [
  * @param func - Function to be tested
  * @param testData - Array of test data
  */
-function testFunction(func: (...args: any[]) => unknown, testData: TestData[]) {
+function testFunction(
+	func: (...args: unknown[]) => unknown,
+	testData: TestData[],
+) {
 	const boundFunc = func.bind(Util);
 
 	for (const data of testData) {
diff --git a/tests/mocks/webextension-polyfill.ts b/tests/mocks/webextension-polyfill.ts
index d2431881..76d09c68 100644
--- a/tests/mocks/webextension-polyfill.ts
+++ b/tests/mocks/webextension-polyfill.ts
@@ -27,7 +27,7 @@ class StorageAreaStub {
 }
 
 const messages = {
-	getSongInfo: (payload: any) => {
+	getSongInfo: (payload: { song: CloneableSong }) => {
 		if (
 			payload.song.processed.artist === 'フミンニッキ' &&
 			payload.song.processed.track === 'Re:start'