Merge pull request #209 from NebulaServices/main

q
This commit is contained in:
rift 2024-01-12 12:22:15 -06:00 committed by GitHub
commit b38a597b7e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 2493 additions and 1378 deletions

View file

@ -2,12 +2,10 @@
NebulaWeb is an official flagship of Nebula Services and Nebula Developer Labs. NebulaWeb is a stunning, sleek, and functional web-proxy with support for thousands of popular sites. With NebulaWeb, the sky is the limit. NebulaWeb is an official flagship of Nebula Services and Nebula Developer Labs. NebulaWeb is a stunning, sleek, and functional web-proxy with support for thousands of popular sites. With NebulaWeb, the sky is the limit.
![license](https://img.shields.io/badge/License-GNU%20AGPL%20v3-blue) ![license](https://img.shields.io/badge/License-GNU%20AGPL%20v3-blue)
## Features ## Features
- Stunning and highly functional UI - Stunning and highly functional UI
- 3 different backend proxies - 3 different backend proxies
- Hides your IP from sites - Hides your IP from sites
@ -18,20 +16,21 @@ NebulaWeb is an official flagship of Nebula Services and Nebula Developer Labs.
# Deployment # Deployment
Table of contents Table of contents
- Deployment - Deployment
--- ---
## Deployment ## Deployment
Run these commands on your server: Run these commands on your server:
`git clone https://https://github.com/NebulaServices/Nebula.git` `git clone https://github.com/NebulaServices/Nebula.git`
`pnpm i` `pnpm i`
`npm run bstart` `npm run bstart`
You may also need to run `npm i -g pnpm tsx` You may also need to run `npm i -g pnpm tsx`
Thanks for using Nebula! Thanks for using Nebula!
## Tech Stack ## Tech Stack
- TypeScript, Tailwind - TypeScript, Tailwind
@ -58,6 +57,7 @@ For support, join our discord: discord.gg/unblocker
- [Dynamic (one of the proxies we use)](https://github.com/NebulaServices/Dynamic) - [Dynamic (one of the proxies we use)](https://github.com/NebulaServices/Dynamic)
- [Rammerhead (one of the proxies we use)](https://github.com/binary-person/rammerhead) - [Rammerhead (one of the proxies we use)](https://github.com/binary-person/rammerhead)
- [Bare Server Node](https://github.com/tomphttp/bare-server-node) - [Bare Server Node](https://github.com/tomphttp/bare-server-node)
- [Catppuccin (for the themes)](https://github.com/catppuccin/catppuccin)
## License ## License

View file

@ -14,6 +14,7 @@
<script src="/uv/uv.bundle.js"></script> <script src="/uv/uv.bundle.js"></script>
<script src="/uv/uv.config.js"></script> <script src="/uv/uv.config.js"></script>
<script src="/dynamic/dynamic.config.js"></script> <script src="/dynamic/dynamic.config.js"></script>
<script src="/localforage/localforage.min.js" defer></script>
<script> <script>
if ("serviceWorker" in navigator) { if ("serviceWorker" in navigator) {
window.addEventListener("load", () => { window.addEventListener("load", () => {

View file

@ -13,13 +13,16 @@
"dependencies": { "dependencies": {
"@fastify/compress": "^6.5.0", "@fastify/compress": "^6.5.0",
"@fastify/static": "^6.12.0", "@fastify/static": "^6.12.0",
"@titaniumnetwork-dev/ultraviolet": "^2.0.0", "@nebula-services/dynamic": "0.7.2-patch.2",
"@nebula-services/ultraviolet": "1.0.1-1.patch.5",
"@tomphttp/bare-server-node": "^2.0.1", "@tomphttp/bare-server-node": "^2.0.1",
"classnames": "^2.3.2", "classnames": "^2.3.2",
"crypto-js": "^4.2.0",
"fastify": "^4.25.1", "fastify": "^4.25.1",
"framer-motion": "^10.16.16", "framer-motion": "^10.16.16",
"i18next": "^23.7.9", "i18next": "^23.7.9",
"i18next-browser-languagedetector": "^7.2.0", "i18next-browser-languagedetector": "^7.2.0",
"localforage": "^1.10.0",
"million": "^2.6.4", "million": "^2.6.4",
"preact": "^10.13.1", "preact": "^10.13.1",
"preact-iso": "^2.3.2", "preact-iso": "^2.3.2",
@ -29,6 +32,7 @@
"react-helmet": "^6.1.0", "react-helmet": "^6.1.0",
"react-i18next": "^13.5.0", "react-i18next": "^13.5.0",
"react-icons": "^4.12.0", "react-icons": "^4.12.0",
"react-toastify": "^9.1.3",
"tsx": "^4.7.0" "tsx": "^4.7.0"
}, },
"devDependencies": { "devDependencies": {

516
pnpm-lock.yaml generated
View file

@ -11,27 +11,36 @@ dependencies:
'@fastify/static': '@fastify/static':
specifier: ^6.12.0 specifier: ^6.12.0
version: 6.12.0 version: 6.12.0
'@titaniumnetwork-dev/ultraviolet': '@nebula-services/dynamic':
specifier: ^2.0.0 specifier: 0.7.2-patch.2
version: 2.0.0 version: 0.7.2-patch.2
'@nebula-services/ultraviolet':
specifier: 1.0.1-1.patch.5
version: 1.0.1-1.patch.5
'@tomphttp/bare-server-node': '@tomphttp/bare-server-node':
specifier: ^2.0.1 specifier: ^2.0.1
version: 2.0.1 version: 2.0.1
classnames: classnames:
specifier: ^2.3.2 specifier: ^2.3.2
version: 2.3.2 version: 2.3.2
crypto-js:
specifier: ^4.2.0
version: 4.2.0
fastify: fastify:
specifier: ^4.25.1 specifier: ^4.25.1
version: 4.25.1 version: 4.25.1
framer-motion: framer-motion:
specifier: ^10.16.16 specifier: ^10.16.16
version: 10.16.16(react@18.2.0) version: 10.16.16(react-dom@18.2.0)(react@18.2.0)
i18next: i18next:
specifier: ^23.7.9 specifier: ^23.7.9
version: 23.7.10 version: 23.7.10
i18next-browser-languagedetector: i18next-browser-languagedetector:
specifier: ^7.2.0 specifier: ^7.2.0
version: 7.2.0 version: 7.2.0
localforage:
specifier: ^1.10.0
version: 1.10.0
million: million:
specifier: ^2.6.4 specifier: ^2.6.4
version: 2.6.4 version: 2.6.4
@ -55,10 +64,13 @@ dependencies:
version: 6.1.0(react@18.2.0) version: 6.1.0(react@18.2.0)
react-i18next: react-i18next:
specifier: ^13.5.0 specifier: ^13.5.0
version: 13.5.0(i18next@23.7.10)(react@18.2.0) version: 13.5.0(i18next@23.7.10)(react-dom@18.2.0)(react@18.2.0)
react-icons: react-icons:
specifier: ^4.12.0 specifier: ^4.12.0
version: 4.12.0(react@18.2.0) version: 4.12.0(react@18.2.0)
react-toastify:
specifier: ^9.1.3
version: 9.1.3(react-dom@18.2.0)(react@18.2.0)
tsx: tsx:
specifier: ^4.7.0 specifier: ^4.7.0
version: 4.7.0 version: 4.7.0
@ -383,6 +395,14 @@ packages:
'@babel/helper-validator-identifier': 7.22.20 '@babel/helper-validator-identifier': 7.22.20
to-fast-properties: 2.0.0 to-fast-properties: 2.0.0
/@dynamic-pkg/mime@1.0.1:
resolution: {integrity: sha512-uZ16uKblCpCWRvF2oPx+hE3Oo+co6NLoEFdA4vWka7+ywoWcQlpbXkNucWoSvLS8V0eTqZIEGx3xJ7rwPUXleg==}
dev: false
/@dynamic-pkg/mutation@1.0.0:
resolution: {integrity: sha512-Xi61JMWcP022hBsYyKJ+0iOzHzSkFf+5qbCs0I2tFmwNaH6jB1kkHGPOEtXmn6/wNgE7/AJV0rj5DEGSnamlnw==}
dev: false
/@emotion/is-prop-valid@0.8.8: /@emotion/is-prop-valid@0.8.8:
resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==}
requiresBuild: true requiresBuild: true
@ -978,6 +998,50 @@ packages:
resolution: {integrity: sha512-n3/+wko8WFd/fbiPCOuBB6HfKL6hTcygFEZ/MpmvpMRbgDSdlNMopDFGjsoTYqCbzTVTX9TL/StXco4yx2v58Q==} resolution: {integrity: sha512-n3/+wko8WFd/fbiPCOuBB6HfKL6hTcygFEZ/MpmvpMRbgDSdlNMopDFGjsoTYqCbzTVTX9TL/StXco4yx2v58Q==}
dev: true dev: true
/@nebula-services/dynamic@0.7.2-patch.2:
resolution: {integrity: sha512-0g1ygwVNS0dmT38NIeZYc2Z5HiZKHT3tP7ZagIeWC/VlcZjINIPR4ThNndWVaGiZey2Y2JS2807ABb41OSYTrw==}
dependencies:
'@dynamic-pkg/mime': 1.0.1
'@dynamic-pkg/mutation': 1.0.0
'@fastify/compress': 6.5.0
'@fastify/static': 6.12.0
'@tomphttp/bare-client': 2.2.0-alpha
'@tomphttp/bare-server-node': 2.0.1
acorn: 8.11.2
astring: 1.8.6
chalk: 5.3.0
cookie: 0.5.0
crypto-js: 4.2.0
domhandler: 5.0.3
esbuild: 0.19.10
fastify: 4.25.1
git-commit-info: 2.0.2
idb: 7.1.1
open: 9.1.0
parse5: 7.1.2
path-browserify: 1.0.1
set-cookie-parser: 2.6.0
transitivePeerDependencies:
- bufferutil
- supports-color
- utf-8-validate
dev: false
/@nebula-services/ultraviolet@1.0.1-1.patch.5:
resolution: {integrity: sha512-EDwbh+AXPg+JxPcPhRHJh6crLh1AHSodcAgfO47ug4paoLkWXE0ELU5Tm0Um38kguTBHzTOPFSzNULpaFbhFLw==}
dependencies:
'@tomphttp/bare-client': 1.1.2-beta.3
crypto-js: 4.2.0
css-tree: 2.3.1
esotope-hammerhead: 0.6.7
events: 3.3.0
idb: 7.1.1
meriyah: 4.3.9
mime-db: 1.52.0
parse5: 7.1.2
set-cookie-parser: 2.6.0
dev: false
/@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1: /@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1:
resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==}
dependencies: dependencies:
@ -1191,22 +1255,12 @@ packages:
dev: true dev: true
optional: true optional: true
/@titaniumnetwork-dev/ultraviolet@2.0.0: /@tomphttp/bare-client@1.1.2-beta.3:
resolution: {integrity: sha512-zRjwip5yFr1p3/1WTb7nmbqmJKNIoxvhbaKFaKr1eSw1Px/Y/nBwPZ+AW+aKVAPFZvx/wAb14eTf2BAH7zklaQ==} resolution: {integrity: sha512-WyIVnSAqzfrLejmOhh/l/LtDOeK+SHnBGi/z+QyliVP1T1JxoNE5eecwxlV+osM9J6FTAYVGNHr8/5bubaIj6Q==}
dependencies:
'@tomphttp/bare-client': 2.1.0
css-tree: 2.3.1
esotope-hammerhead: 0.6.7
events: 3.3.0
idb: 7.1.1
meriyah: 4.3.9
mime-db: 1.52.0
parse5: 7.1.2
set-cookie-parser: 2.6.0
dev: false dev: false
/@tomphttp/bare-client@2.1.0: /@tomphttp/bare-client@2.2.0-alpha:
resolution: {integrity: sha512-0s2g3bpKAxwk7sOsfewpngLF+2lQrS0mxnga+6qIzKCoYdOKd5+Lm3lkEDHO0cWIEqMbgRZB2wjW1+NQ2XbGWA==} resolution: {integrity: sha512-xhcflOpwr92tkpp8SoDhB3nK3LHMBIjx+vgow37XobQew2k0/mXSxmaU7BsDFpOIa1CcLCEsR8gWn0v7Cy9+7Q==}
dev: false dev: false
/@tomphttp/bare-server-node@2.0.1: /@tomphttp/bare-server-node@2.0.1:
@ -1596,6 +1650,11 @@ packages:
'@mdn/browser-compat-data': 5.4.5 '@mdn/browser-compat-data': 5.4.5
dev: true dev: true
/astring@1.8.6:
resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==}
hasBin: true
dev: false
/async-exit-hook@2.0.1: /async-exit-hook@2.0.1:
resolution: {integrity: sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==} resolution: {integrity: sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==}
engines: {node: '>=0.12.0'} engines: {node: '>=0.12.0'}
@ -1664,6 +1723,11 @@ packages:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
dev: false dev: false
/big-integer@1.6.52:
resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==}
engines: {node: '>=0.6'}
dev: false
/binary-extensions@2.2.0: /binary-extensions@2.2.0:
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -1676,6 +1740,13 @@ packages:
resolution: {integrity: sha512-Fk23J0+vRnI2eKDEDoUZXWtbMjijr098lKhuj4DKAfMKMCRVfJOuxXlbpxy0sTgbZ/Nr2N8MexmOir+GGI/ZMA==} resolution: {integrity: sha512-Fk23J0+vRnI2eKDEDoUZXWtbMjijr098lKhuj4DKAfMKMCRVfJOuxXlbpxy0sTgbZ/Nr2N8MexmOir+GGI/ZMA==}
dev: false dev: false
/bplist-parser@0.2.0:
resolution: {integrity: sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==}
engines: {node: '>= 5.10.0'}
dependencies:
big-integer: 1.6.52
dev: false
/brace-expansion@1.1.11: /brace-expansion@1.1.11:
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
dependencies: dependencies:
@ -1715,6 +1786,13 @@ packages:
ieee754: 1.2.1 ieee754: 1.2.1
dev: false dev: false
/bundle-name@3.0.0:
resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==}
engines: {node: '>=12'}
dependencies:
run-applescript: 5.0.0
dev: false
/cacache@15.3.0: /cacache@15.3.0:
resolution: {integrity: sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==} resolution: {integrity: sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
@ -1784,6 +1862,11 @@ packages:
supports-color: 7.2.0 supports-color: 7.2.0
dev: true dev: true
/chalk@5.3.0:
resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==}
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
dev: false
/chokidar@3.5.3: /chokidar@3.5.3:
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
engines: {node: '>= 8.10.0'} engines: {node: '>= 8.10.0'}
@ -1827,6 +1910,11 @@ packages:
wrap-ansi: 7.0.0 wrap-ansi: 7.0.0
dev: true dev: true
/clsx@1.2.1:
resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==}
engines: {node: '>=6'}
dev: false
/color-convert@1.9.3: /color-convert@1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
dependencies: dependencies:
@ -1907,6 +1995,14 @@ packages:
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
dev: false dev: false
/cross-spawn@5.1.0:
resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==}
dependencies:
lru-cache: 4.1.5
shebang-command: 1.2.0
which: 1.3.1
dev: false
/cross-spawn@7.0.3: /cross-spawn@7.0.3:
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@ -1914,7 +2010,10 @@ packages:
path-key: 3.1.1 path-key: 3.1.1
shebang-command: 2.0.0 shebang-command: 2.0.0
which: 2.0.2 which: 2.0.2
dev: true
/crypto-js@4.2.0:
resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
dev: false
/crypto-md5@1.0.0: /crypto-md5@1.0.0:
resolution: {integrity: sha512-65Mtei8+EkSIK+5Ie4gpWXoJ/5bgpqPXFknHHXAyhDqKsEAAzUslGd8mOeawbfcuQ8fADNKcF4xQA3fqlZJ8Ig==} resolution: {integrity: sha512-65Mtei8+EkSIK+5Ie4gpWXoJ/5bgpqPXFknHHXAyhDqKsEAAzUslGd8mOeawbfcuQ8fADNKcF4xQA3fqlZJ8Ig==}
@ -1987,6 +2086,24 @@ packages:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
dev: true dev: true
/default-browser-id@3.0.0:
resolution: {integrity: sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==}
engines: {node: '>=12'}
dependencies:
bplist-parser: 0.2.0
untildify: 4.0.0
dev: false
/default-browser@4.0.0:
resolution: {integrity: sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==}
engines: {node: '>=14.16'}
dependencies:
bundle-name: 3.0.0
default-browser-id: 3.0.0
execa: 7.2.0
titleize: 3.0.0
dev: false
/define-data-property@1.1.1: /define-data-property@1.1.1:
resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -1996,6 +2113,11 @@ packages:
has-property-descriptors: 1.0.1 has-property-descriptors: 1.0.1
dev: true dev: true
/define-lazy-prop@3.0.0:
resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==}
engines: {node: '>=12'}
dev: false
/define-properties@1.2.1: /define-properties@1.2.1:
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -2048,6 +2170,17 @@ packages:
esutils: 2.0.3 esutils: 2.0.3
dev: true dev: true
/domelementtype@2.3.0:
resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
dev: false
/domhandler@5.0.3:
resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
engines: {node: '>= 4'}
dependencies:
domelementtype: 2.3.0
dev: false
/dotenv@16.3.1: /dotenv@16.3.1:
resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -2504,6 +2637,64 @@ packages:
engines: {node: '>=0.8.x'} engines: {node: '>=0.8.x'}
dev: false dev: false
/execa@0.6.3:
resolution: {integrity: sha512-/teX3MDLFBdYUhRk8WCBYboIMUmqeizu0m9Z3YF3JWrbEh/SlZg00vLJSaAGWw3wrZ9tE0buNw79eaAPYhUuvg==}
engines: {node: '>=4'}
dependencies:
cross-spawn: 5.1.0
get-stream: 3.0.0
is-stream: 1.1.0
npm-run-path: 2.0.2
p-finally: 1.0.0
signal-exit: 3.0.7
strip-eof: 1.0.0
dev: false
/execa@4.1.0:
resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==}
engines: {node: '>=10'}
dependencies:
cross-spawn: 7.0.3
get-stream: 5.2.0
human-signals: 1.1.1
is-stream: 2.0.1
merge-stream: 2.0.0
npm-run-path: 4.0.1
onetime: 5.1.2
signal-exit: 3.0.7
strip-final-newline: 2.0.0
dev: false
/execa@5.1.1:
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
engines: {node: '>=10'}
dependencies:
cross-spawn: 7.0.3
get-stream: 6.0.1
human-signals: 2.1.0
is-stream: 2.0.1
merge-stream: 2.0.0
npm-run-path: 4.0.1
onetime: 5.1.2
signal-exit: 3.0.7
strip-final-newline: 2.0.0
dev: false
/execa@7.2.0:
resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==}
engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0}
dependencies:
cross-spawn: 7.0.3
get-stream: 6.0.1
human-signals: 4.3.1
is-stream: 3.0.0
merge-stream: 2.0.0
npm-run-path: 5.2.0
onetime: 6.0.0
signal-exit: 3.0.7
strip-final-newline: 3.0.0
dev: false
/fast-content-type-parse@1.1.0: /fast-content-type-parse@1.1.0:
resolution: {integrity: sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==} resolution: {integrity: sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==}
dev: false dev: false
@ -2651,7 +2842,7 @@ packages:
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
dev: true dev: true
/framer-motion@10.16.16(react@18.2.0): /framer-motion@10.16.16(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-je6j91rd7NmUX7L1XHouwJ4v3R+SO4umso2LUcgOct3rHZ0PajZ80ETYZTajzEXEl9DlKyzjyt4AvGQ+lrebOw==} resolution: {integrity: sha512-je6j91rd7NmUX7L1XHouwJ4v3R+SO4umso2LUcgOct3rHZ0PajZ80ETYZTajzEXEl9DlKyzjyt4AvGQ+lrebOw==}
peerDependencies: peerDependencies:
react: ^18.0.0 react: ^18.0.0
@ -2663,6 +2854,7 @@ packages:
optional: true optional: true
dependencies: dependencies:
react: 18.2.0 react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
tslib: 2.6.2 tslib: 2.6.2
optionalDependencies: optionalDependencies:
'@emotion/is-prop-valid': 0.8.8 '@emotion/is-prop-valid': 0.8.8
@ -2768,6 +2960,23 @@ packages:
hasown: 2.0.0 hasown: 2.0.0
dev: true dev: true
/get-stream@3.0.0:
resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==}
engines: {node: '>=4'}
dev: false
/get-stream@5.2.0:
resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==}
engines: {node: '>=8'}
dependencies:
pump: 3.0.0
dev: false
/get-stream@6.0.1:
resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
engines: {node: '>=10'}
dev: false
/get-symbol-description@1.0.0: /get-symbol-description@1.0.0:
resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -2782,6 +2991,14 @@ packages:
resolve-pkg-maps: 1.0.0 resolve-pkg-maps: 1.0.0
dev: false dev: false
/git-commit-info@2.0.2:
resolution: {integrity: sha512-QOgPqeTkFiIQr3TW/ekG2U6s1x7OkNdR+2XsapmXHiGImO5Qx2cilx2HmGPrihIqmV0WWCo5H+B938lQ/vAAfA==}
dependencies:
execa: 4.1.0
is-git-repository: 1.1.1
path-is-absolute: 1.0.1
dev: false
/glob-parent@5.1.2: /glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
@ -2965,6 +3182,21 @@ packages:
- supports-color - supports-color
dev: false dev: false
/human-signals@1.1.1:
resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==}
engines: {node: '>=8.12.0'}
dev: false
/human-signals@2.1.0:
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
engines: {node: '>=10.17.0'}
dev: false
/human-signals@4.3.1:
resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==}
engines: {node: '>=14.18.0'}
dev: false
/humanize-ms@1.2.1: /humanize-ms@1.2.1:
resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==}
requiresBuild: true requiresBuild: true
@ -3014,6 +3246,10 @@ packages:
engines: {node: '>= 4'} engines: {node: '>= 4'}
dev: true dev: true
/immediate@3.0.6:
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
dev: false
/import-fresh@3.3.0: /import-fresh@3.3.0:
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -3134,6 +3370,18 @@ packages:
has-tostringtag: 1.0.0 has-tostringtag: 1.0.0
dev: true dev: true
/is-docker@2.2.1:
resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
engines: {node: '>=8'}
hasBin: true
dev: false
/is-docker@3.0.0:
resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
hasBin: true
dev: false
/is-extglob@2.1.1: /is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -3155,12 +3403,27 @@ packages:
has-tostringtag: 1.0.0 has-tostringtag: 1.0.0
dev: true dev: true
/is-git-repository@1.1.1:
resolution: {integrity: sha512-hxLpJytJnIZ5Og5QsxSkzmb8Qx8rGau9bio1JN/QtXcGEFuSsQYau0IiqlsCwftsfVYjF1mOq6uLdmwNSspgpA==}
dependencies:
execa: 0.6.3
path-is-absolute: 1.0.1
dev: false
/is-glob@4.0.3: /is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dependencies: dependencies:
is-extglob: 2.1.1 is-extglob: 2.1.1
/is-inside-container@1.0.0:
resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
engines: {node: '>=14.16'}
hasBin: true
dependencies:
is-docker: 3.0.0
dev: false
/is-lambda@1.0.1: /is-lambda@1.0.1:
resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==}
requiresBuild: true requiresBuild: true
@ -3210,6 +3473,21 @@ packages:
call-bind: 1.0.5 call-bind: 1.0.5
dev: true dev: true
/is-stream@1.1.0:
resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==}
engines: {node: '>=0.10.0'}
dev: false
/is-stream@2.0.1:
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
engines: {node: '>=8'}
dev: false
/is-stream@3.0.0:
resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dev: false
/is-string@1.0.7: /is-string@1.0.7:
resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -3248,6 +3526,13 @@ packages:
get-intrinsic: 1.2.2 get-intrinsic: 1.2.2
dev: true dev: true
/is-wsl@2.2.0:
resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
engines: {node: '>=8'}
dependencies:
is-docker: 2.2.1
dev: false
/isarray@1.0.0: /isarray@1.0.0:
resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
dev: false dev: false
@ -3357,6 +3642,12 @@ packages:
type-check: 0.4.0 type-check: 0.4.0
dev: true dev: true
/lie@3.1.1:
resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==}
dependencies:
immediate: 3.0.6
dev: false
/light-my-request@5.11.0: /light-my-request@5.11.0:
resolution: {integrity: sha512-qkFCeloXCOMpmEdZ/MV91P8AT4fjwFXWaAFz3lUeStM8RcoM1ks4J/F8r1b3r6y/H4u3ACEJ1T+Gv5bopj7oDA==} resolution: {integrity: sha512-qkFCeloXCOMpmEdZ/MV91P8AT4fjwFXWaAFz3lUeStM8RcoM1ks4J/F8r1b3r6y/H4u3ACEJ1T+Gv5bopj7oDA==}
dependencies: dependencies:
@ -3379,6 +3670,12 @@ packages:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
dev: true dev: true
/localforage@1.10.0:
resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==}
dependencies:
lie: 3.1.1
dev: false
/locate-path@6.0.0: /locate-path@6.0.0:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -3407,6 +3704,13 @@ packages:
resolution: {integrity: sha512-qkisDmHMe8gxKujmC1BdaqgkoFlioLDCUwaFBA3lX8Ilhr3YzsasbGYaiADMjxQnj+aiZUKgGKe/BN3skMwXWw==} resolution: {integrity: sha512-qkisDmHMe8gxKujmC1BdaqgkoFlioLDCUwaFBA3lX8Ilhr3YzsasbGYaiADMjxQnj+aiZUKgGKe/BN3skMwXWw==}
dev: false dev: false
/lru-cache@4.1.5:
resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==}
dependencies:
pseudomap: 1.0.2
yallist: 2.1.2
dev: false
/lru-cache@5.1.1: /lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
dependencies: dependencies:
@ -3468,6 +3772,10 @@ packages:
readable-stream: 2.3.8 readable-stream: 2.3.8
dev: false dev: false
/merge-stream@2.0.0:
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
dev: false
/merge2@1.4.1: /merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@ -3524,6 +3832,16 @@ packages:
hasBin: true hasBin: true
dev: false dev: false
/mimic-fn@2.1.0:
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
engines: {node: '>=6'}
dev: false
/mimic-fn@4.0.0:
resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
engines: {node: '>=12'}
dev: false
/minimatch@3.1.2: /minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
dependencies: dependencies:
@ -3718,6 +4036,27 @@ packages:
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dev: true dev: true
/npm-run-path@2.0.2:
resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==}
engines: {node: '>=4'}
dependencies:
path-key: 2.0.1
dev: false
/npm-run-path@4.0.1:
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
engines: {node: '>=8'}
dependencies:
path-key: 3.1.1
dev: false
/npm-run-path@5.2.0:
resolution: {integrity: sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
path-key: 4.0.0
dev: false
/npmlog@5.0.1: /npmlog@5.0.1:
resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==}
dependencies: dependencies:
@ -3811,6 +4150,30 @@ packages:
dependencies: dependencies:
wrappy: 1.0.2 wrappy: 1.0.2
/onetime@5.1.2:
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
engines: {node: '>=6'}
dependencies:
mimic-fn: 2.1.0
dev: false
/onetime@6.0.0:
resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
engines: {node: '>=12'}
dependencies:
mimic-fn: 4.0.0
dev: false
/open@9.1.0:
resolution: {integrity: sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==}
engines: {node: '>=14.16'}
dependencies:
default-browser: 4.0.0
define-lazy-prop: 3.0.0
is-inside-container: 1.0.0
is-wsl: 2.2.0
dev: false
/optionator@0.9.3: /optionator@0.9.3:
resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
@ -3827,6 +4190,11 @@ packages:
resolution: {integrity: sha512-E3Orl5pvDJXnVmpaAA2TeNNpNhTMl4o5HghuWhOivBjEiTnJSrMYSa5uZMek1lBEvu8kKEsa2YgVcGFVDqX/9w==} resolution: {integrity: sha512-E3Orl5pvDJXnVmpaAA2TeNNpNhTMl4o5HghuWhOivBjEiTnJSrMYSa5uZMek1lBEvu8kKEsa2YgVcGFVDqX/9w==}
dev: false dev: false
/p-finally@1.0.0:
resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==}
engines: {node: '>=4'}
dev: false
/p-is-promise@3.0.0: /p-is-promise@3.0.0:
resolution: {integrity: sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==} resolution: {integrity: sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -3871,6 +4239,10 @@ packages:
entities: 4.5.0 entities: 4.5.0
dev: false dev: false
/path-browserify@1.0.1:
resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
dev: false
/path-exists@4.0.0: /path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -3880,10 +4252,19 @@ packages:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
/path-key@2.0.1:
resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==}
engines: {node: '>=4'}
dev: false
/path-key@3.1.1: /path-key@3.1.1:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'} engines: {node: '>=8'}
dev: true
/path-key@4.0.0:
resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
engines: {node: '>=12'}
dev: false
/path-parse@1.0.7: /path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
@ -4175,6 +4556,10 @@ packages:
ipaddr.js: 1.9.1 ipaddr.js: 1.9.1
dev: false dev: false
/pseudomap@1.0.2:
resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==}
dev: false
/psl@1.9.0: /psl@1.9.0:
resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==}
dev: false dev: false
@ -4206,6 +4591,16 @@ packages:
resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
dev: false dev: false
/react-dom@18.2.0(react@18.2.0):
resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
peerDependencies:
react: ^18.2.0
dependencies:
loose-envify: 1.4.0
react: 18.2.0
scheduler: 0.23.0
dev: false
/react-fast-compare@3.2.2: /react-fast-compare@3.2.2:
resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==}
dev: false dev: false
@ -4222,7 +4617,7 @@ packages:
react-side-effect: 2.1.2(react@18.2.0) react-side-effect: 2.1.2(react@18.2.0)
dev: false dev: false
/react-i18next@13.5.0(i18next@23.7.10)(react@18.2.0): /react-i18next@13.5.0(i18next@23.7.10)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-CFJ5NDGJ2MUyBohEHxljOq/39NQ972rh1ajnadG9BjTk+UXbHLq4z5DKEbEQBDoIhUmmbuS/fIMJKo6VOax1HA==} resolution: {integrity: sha512-CFJ5NDGJ2MUyBohEHxljOq/39NQ972rh1ajnadG9BjTk+UXbHLq4z5DKEbEQBDoIhUmmbuS/fIMJKo6VOax1HA==}
peerDependencies: peerDependencies:
i18next: '>= 23.2.3' i18next: '>= 23.2.3'
@ -4239,6 +4634,7 @@ packages:
html-parse-stringify: 3.0.1 html-parse-stringify: 3.0.1
i18next: 23.7.10 i18next: 23.7.10
react: 18.2.0 react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false dev: false
/react-icons@4.12.0(react@18.2.0): /react-icons@4.12.0(react@18.2.0):
@ -4260,6 +4656,17 @@ packages:
react: 18.2.0 react: 18.2.0
dev: false dev: false
/react-toastify@9.1.3(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-fPfb8ghtn/XMxw3LkxQBk3IyagNpF/LIKjOBflbexr2AWxAH1MJgvnESwEwBn9liLFXgTKWgBSdZpw9m4OTHTg==}
peerDependencies:
react: '>=16'
react-dom: '>=16'
dependencies:
clsx: 1.2.1
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
/react@18.2.0: /react@18.2.0:
resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -4450,6 +4857,13 @@ packages:
fsevents: 2.3.3 fsevents: 2.3.3
dev: true dev: true
/run-applescript@5.0.0:
resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==}
engines: {node: '>=12'}
dependencies:
execa: 5.1.1
dev: false
/run-parallel@1.2.0: /run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
dependencies: dependencies:
@ -4503,6 +4917,12 @@ packages:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
dev: false dev: false
/scheduler@0.23.0:
resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==}
dependencies:
loose-envify: 1.4.0
dev: false
/secure-json-parse@2.7.0: /secure-json-parse@2.7.0:
resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==}
dev: false dev: false
@ -4554,17 +4974,27 @@ packages:
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
dev: false dev: false
/shebang-command@1.2.0:
resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==}
engines: {node: '>=0.10.0'}
dependencies:
shebang-regex: 1.0.0
dev: false
/shebang-command@2.0.0: /shebang-command@2.0.0:
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
engines: {node: '>=8'} engines: {node: '>=8'}
dependencies: dependencies:
shebang-regex: 3.0.0 shebang-regex: 3.0.0
dev: true
/shebang-regex@1.0.0:
resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==}
engines: {node: '>=0.10.0'}
dev: false
/shebang-regex@3.0.0: /shebang-regex@3.0.0:
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
engines: {node: '>=8'} engines: {node: '>=8'}
dev: true
/shell-quote@1.8.1: /shell-quote@1.8.1:
resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==}
@ -4776,6 +5206,21 @@ packages:
dependencies: dependencies:
ansi-regex: 5.0.1 ansi-regex: 5.0.1
/strip-eof@1.0.0:
resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==}
engines: {node: '>=0.10.0'}
dev: false
/strip-final-newline@2.0.0:
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
engines: {node: '>=6'}
dev: false
/strip-final-newline@3.0.0:
resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
engines: {node: '>=12'}
dev: false
/strip-json-comments@3.1.1: /strip-json-comments@3.1.1:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -4925,6 +5370,11 @@ packages:
xtend: 4.0.2 xtend: 4.0.2
dev: false dev: false
/titleize@3.0.0:
resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==}
engines: {node: '>=12'}
dev: false
/tmp-promise@1.1.0: /tmp-promise@1.1.0:
resolution: {integrity: sha512-8+Ah9aB1IRXCnIOxXZ0uFozV1nMU5xiu7hhFVUSxZ3bYu+psD4TzagCzVbexUCgNNGJnsmNDQlS4nG3mTyoNkw==} resolution: {integrity: sha512-8+Ah9aB1IRXCnIOxXZ0uFozV1nMU5xiu7hhFVUSxZ3bYu+psD4TzagCzVbexUCgNNGJnsmNDQlS4nG3mTyoNkw==}
dependencies: dependencies:
@ -5127,6 +5577,11 @@ packages:
webpack-virtual-modules: 0.6.1 webpack-virtual-modules: 0.6.1
dev: false dev: false
/untildify@4.0.0:
resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==}
engines: {node: '>=8'}
dev: false
/update-browserslist-db@1.0.13(browserslist@4.22.2): /update-browserslist-db@1.0.13(browserslist@4.22.2):
resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==}
hasBin: true hasBin: true
@ -5281,6 +5736,13 @@ packages:
has-tostringtag: 1.0.0 has-tostringtag: 1.0.0
dev: true dev: true
/which@1.3.1:
resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==}
hasBin: true
dependencies:
isexe: 2.0.0
dev: false
/which@2.0.2: /which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@ -5329,6 +5791,10 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
dev: true dev: true
/yallist@2.1.2:
resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==}
dev: false
/yallist@3.1.1: /yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}

File diff suppressed because one or more lines are too long

View file

@ -2,7 +2,7 @@
self.__dynamic$config = { self.__dynamic$config = {
prefix: '/~/dynamic/', prefix: '/~/dynamic/',
encoding: 'plain', encoding: 'aes',
mode: 'production', mode: 'production',
logLevel: 0, logLevel: 0,
bare: { bare: {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
public/generic_globe.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -3,11 +3,39 @@ importScripts("/uv/uv.config.js");
importScripts(__uv$config.sw || "/uv/uv.sw.js"); importScripts(__uv$config.sw || "/uv/uv.sw.js");
importScripts("/dynamic/dynamic.config.js"); importScripts("/dynamic/dynamic.config.js");
importScripts("/dynamic/dynamic.worker.js"); importScripts("/dynamic/dynamic.worker.js");
//import our IDB lib
importScripts("/localforage/localforage.min.js");
localforage.config({
driver: localforage.INDEXEDDB,
name: "Nebula",
version: 1.0,
storeName: "nebula_config",
description: "Nebula Config for things reliant on IndexedDB"
});
const sw = new UVServiceWorker(); const dynPromise = new Promise(async (resolve) => {
const dynamic = new Dynamic(); try {
const bare =
(await localforage.getItem("bare")) || location.origin + "/bare/";
self.__dynamic$config.bare.path = bare;
self.dynamic = new Dynamic(self.__dynamic$config);
} catch (error) {
console.log(error);
}
resolve();
});
self.dynamic = dynamic; const uvPromise = new Promise(async (resolve) => {
try {
const bare =
(await localforage.getItem("bare")) || location.origin + "/bare/";
self.__uv$config.bare = bare;
self.uv = new UVServiceWorker(self.__uv$config);
} catch (error) {
console.log(error);
}
resolve();
});
self.addEventListener("fetch", (event) => { self.addEventListener("fetch", (event) => {
if ( if (
@ -15,16 +43,25 @@ self.addEventListener("fetch", (event) => {
) { ) {
event.respondWith( event.respondWith(
(async function () { (async function () {
if (await dynamic.route(event)) { try {
return await dynamic.fetch(event); await dynPromise;
} catch (error) {}
if (await self.dynamic.route(event)) {
return await self.dynamic.fetch(event);
} }
await fetch(event.request);
return await fetch(event.request);
})() })()
); );
} else if ( } else if (
event.request.url.startsWith(location.origin + __uv$config.prefix) event.request.url.startsWith(location.origin + self.__uv$config.prefix)
) { ) {
event.respondWith(sw.fetch(event)); event.respondWith(
(async function () {
try {
await uvPromise;
} catch (error) {}
return await self.uv.fetch(event);
})()
);
} }
}); });

View file

@ -0,0 +1,30 @@
@import url("https://fonts.googleapis.com/css2?family=Dongle&family=Roboto:wght@100&display=swap");
:root {
--background-primary: #303446 !important;
--background-lighter: #292c3c !important;
--navbar-color: #292c3c !important;
--navbar-height: 60px !important;
--navbar-text-color: #c6d0f5 !important;
--navbar-link-color: #8caaee !important;
--navbar-link-hover-color: #ca9ee6 !important;
--navbar-font: "Roboto" !important;
--input-text-color: #c6d0f5 !important;
--input-placeholder-color: #a5adce !important;
--input-background-color: #232634 !important;
--input-border-color: color-mix(in srgb, #232634, #ca9ee6 50%) !important;
--input-border-size: 1.3px !important;
--navbar-logo-filter: none !important;
--dropdown-option-hover-color: #232634 !important;
--tab-color: #414559 !important;
--active-color: #ca9ee6 !important;
}
.font-inter {
font-family: "Inter", sans-serif;
font-weight: 300;
}
.font-roboto {
font-family: "Roboto";
}

View file

@ -0,0 +1,30 @@
@import url("https://fonts.googleapis.com/css2?family=Dongle&family=Roboto:wght@100&display=swap");
:root {
--background-primary: #eff1f5 !important;
--background-lighter: #e6e9ef !important;
--navbar-color: #e6e9ef !important;
--navbar-height: 60px !important;
--navbar-text-color: #4c4f69 !important;
--navbar-link-color: #1e66f5 !important;
--navbar-link-hover-color: #8839ef !important;
--navbar-font: "Roboto" !important;
--input-text-color: #4c4f69 !important;
--input-placeholder-color: #6c6f85 !important;
--input-background-color: #dce0e8 !important;
--input-border-color: color-mix(in srgb, #dce0e8, #8839ef 50%) !important;
--input-border-size: 1.3px !important;
--navbar-logo-filter: none !important;
--dropdown-option-hover-color: #dce0e8 !important;
--tab-color: #ccd0da !important;
--active-color: #8839ef !important;
}
.font-inter {
font-family: "Inter", sans-serif;
font-weight: 300;
}
.font-roboto {
font-family: "Roboto";
}

View file

@ -0,0 +1,30 @@
@import url("https://fonts.googleapis.com/css2?family=Dongle&family=Roboto:wght@100&display=swap");
:root {
--background-primary: #24273a !important;
--background-lighter: #1e2030 !important;
--navbar-color: #1e2030 !important;
--navbar-height: 60px !important;
--navbar-text-color: #cad3f5 !important;
--navbar-link-color: #8aadf4 !important;
--navbar-link-hover-color: #c6a0f6 !important;
--navbar-font: "Roboto" !important;
--input-text-color: #cad3f5 !important;
--input-placeholder-color: #a5adcb !important;
--input-background-color: #181926 !important;
--input-border-color: color-mix(in srgb, #181926, #c6a0f6 50%) !important;
--input-border-size: 1.3px !important;
--navbar-logo-filter: none !important;
--dropdown-option-hover-color: #181926 !important;
--tab-color: #363a4f !important;
--active-color: #c6a0f6 !important;
}
.font-inter {
font-family: "Inter", sans-serif;
font-weight: 300;
}
.font-roboto {
font-family: "Roboto";
}

View file

@ -0,0 +1,30 @@
@import url("https://fonts.googleapis.com/css2?family=Dongle&family=Roboto:wght@100&display=swap");
:root {
--background-primary: #1e1e2e !important;
--background-lighter: #181825 !important;
--navbar-color: #181825 !important;
--navbar-height: 60px !important;
--navbar-text-color: #cdd6f4 !important;
--navbar-link-color: #89b4fa !important;
--navbar-link-hover-color: #cba6f7 !important;
--navbar-font: "Roboto" !important;
--input-text-color: #cdd6f4 !important;
--input-placeholder-color: #a6adc8 !important;
--input-background-color: #11111b !important;
--input-border-color: color-mix(in srgb, #11111b, #cba6f7 50%) !important;
--input-border-size: 1.3px !important;
--navbar-logo-filter: none !important;
--dropdown-option-hover-color: #11111b !important;
--tab-color: #313244 !important;
--active-color: #cba6f7 !important;
}
.font-inter {
font-family: "Inter", sans-serif;
font-weight: 300;
}
.font-roboto {
font-family: "Roboto";
}

View file

@ -16,6 +16,7 @@
--input-border-size: 1.3px; --input-border-size: 1.3px;
--navbar-logo-filter: none; --navbar-logo-filter: none;
--dropdown-option-hover-color: #312a49; --dropdown-option-hover-color: #312a49;
--tab-color: var(--black);
} }
.font-inter { .font-inter {

View file

@ -1,8 +1,8 @@
self.__uv$config = { self.__uv$config = {
prefix: "/~/uv/", prefix: "/~/uv/",
bare: "/bare/", bare: "/bare/",
encodeUrl: Ultraviolet.codec.plain.encode, encodeUrl: Ultraviolet.codec.aes.encode,
decodeUrl: Ultraviolet.codec.plain.decode, decodeUrl: Ultraviolet.codec.aes.decode,
handler: "/uv/uv.handler.js", handler: "/uv/uv.handler.js",
client: "/uv/uv.client.js", client: "/uv/uv.client.js",
bundle: "/uv/uv.bundle.js", bundle: "/uv/uv.bundle.js",

View file

@ -77,6 +77,16 @@ app.register(fastifyStatic, {
wildcard: false wildcard: false
}); });
app.get("/search=:query", async (req, res) => {
const { query } = req.params as { query: string }; // Define the type for req.params
const response = await fetch(
`http://api.duckduckgo.com/ac?q=${query}&format=json`
).then((apiRes) => apiRes.json());
res.send(response);
});
app.setNotFoundHandler((req, res) => { app.setNotFoundHandler((req, res) => {
res.sendFile("index.html"); // SPA catch-all res.sendFile("index.html"); // SPA catch-all
}); });

View file

@ -8,6 +8,13 @@ export function AboutBlank(props: { url: string }) {
iframe.style.height = "100%"; iframe.style.height = "100%";
iframe.style.border = "none"; iframe.style.border = "none";
iframe.style.overflow = "hidden"; iframe.style.overflow = "hidden";
iframe.style.margin = "0";
iframe.style.padding = "0";
iframe.style.position = "fixed";
iframe.style.top = "0";
iframe.style.bottom = "0";
iframe.style.left = "0";
iframe.style.right = "0";
newWindow.document.body.appendChild(iframe); newWindow.document.body.appendChild(iframe);
window.location.replace("https://google.com"); window.location.replace("https://google.com");
return ( return (

View file

@ -1,8 +1,8 @@
import './Suspense.css' import "./Suspense.css";
export function LoadSuspense() { export function LoadSuspense() {
return ( return (
<div class="suspenseContainer"> <div className="suspenseContainer">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
version="1.2" version="1.2"
@ -10,7 +10,7 @@ export function LoadSuspense() {
width="400" width="400"
height="400" height="400"
fill="#5e17eb" fill="#5e17eb"
class="animate-pulse-brighter" className="animate-pulse-brighter"
> >
<g id="svgg"> <g id="svgg">
<path <path

View file

@ -1,7 +1,7 @@
import { HeaderButton } from "./HeaderButton"; import { HeaderButton } from "./HeaderButton";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "preact-router"; import { Link } from "preact-router";
import { motion } from "framer-motion" import { motion } from "framer-motion";
// Header icons // Header icons
import { HiOutlineCube } from "react-icons/hi"; import { HiOutlineCube } from "react-icons/hi";
@ -14,50 +14,105 @@ export function Header() {
const [isActive, setIsActive] = useState(false); const [isActive, setIsActive] = useState(false);
return ( return (
<div id="navbar" className="flex h-16 flex-row items-center justify-between bg-navbar-color px-4"> <div
<Link href="/" class="w-1/8"> id="navbar"
<div className="flex flex-row items-center"> className="flex h-16 flex-row items-center justify-between bg-navbar-color px-4"
<img src="/logo.png" alt="Nebula Logo" className="h-16 w-16 transition-all duration-1000 hover:rotate-[360deg]"></img> >
<h1 className="font-roboto text-2xl font-bold text-navbar-text-color md:text-4xl"> <Link href="/" className="w-1/8">
{t("header.title")} <div className="relative flex flex-row items-center">
<img
src="/logo.png"
className="h-16 w-16 transition-all duration-1000 hover:rotate-[360deg]"
alt="Nebula Logo"
></img>
<h1 className="font-roboto invisible whitespace-nowrap text-2xl font-bold text-navbar-text-color sm:visible sm:text-4xl">
{" "}
{t("header.title")}{" "}
</h1> </h1>
</div> </div>
</Link> </Link>
<motion.button type="button" className="z-20 md:hidden text-text-color text-bold text-3xl mr-4" aria-expanded={isActive} aria-controls="navbar-default" onClick={() => setIsActive(!isActive)} initial={{ rotate: 0 }} animate={{ rotate: isActive ? 90 : 0 }} transition={{ duration: 0.5 }} >
<motion.button
type="button"
className="text-bold z-20 mr-4 text-3xl text-text-color md:hidden"
aria-expanded={isActive}
aria-controls="navbar-default"
onClick={() => setIsActive(!isActive)}
initial={{ rotate: 0 }}
animate={{ rotate: isActive ? 90 : 0 }}
transition={{ duration: 0.5 }}
>
<RxHamburgerMenu /> <RxHamburgerMenu />
</motion.button> </motion.button>
{window.innerWidth >= 768 && {window.innerWidth >= 768 && (
//standard menu //standard menu
<div className={`fixed inset-0 z-10 flex md:relative md:right-0 ${ window.innerWidth <= 768 && !isActive && "hidden"}`}> <div
<div className="h-[calc(100%-4rem)] w-full mt-16 lg:h-full lg:mt-auto md:h-full md:mt-auto"> className={`fixed inset-0 z-10 flex md:relative md:right-0 ${
<div className="flex h-full w-full whitespace-nowrap" onClick={() => setIsActive(false)} > window.innerWidth <= 768 && !isActive && "hidden"
}`}
>
<div className="mt-16 h-[calc(100%-4rem)] w-full md:mt-auto md:h-full lg:mt-auto lg:h-full">
<div
className="flex h-full w-full whitespace-nowrap"
onClick={() => setIsActive(false)}
>
<div className="flex w-full flex-col justify-evenly md:flex-row"> <div className="flex w-full flex-col justify-evenly md:flex-row">
<HeaderButton href="/games" Icon={HiOutlineCube} translationKey="header.games" /> <HeaderButton
<HeaderButton href="/settings" Icon={RxMixerVertical} translationKey="header.settings" /> href="/games"
<HeaderButton href="/discord" Icon={RiLinksFill} translationKey="header.discord" /> Icon={HiOutlineCube}
translationKey="header.games"
/>
<HeaderButton
href="/settings"
Icon={RxMixerVertical}
translationKey="header.settings"
/>
<HeaderButton
href="/discord"
Icon={RiLinksFill}
translationKey="header.discord"
/>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
} )}
{window.innerWidth <= 768 && {window.innerWidth <= 768 && (
//animated mobile menu //animated mobile menu
<motion.div className={`fixed inset-0 z-10 flex md:relative md:right-0 ${ window.innerWidth <= 768 && !isActive && "hidden"}`} <motion.div
className={`fixed inset-0 z-10 flex md:relative md:right-0 ${
window.innerWidth <= 768 && !isActive && "hidden"
}`}
initial={{ x: 0 }} initial={{ x: 0 }}
animate={{ x: isActive ? 0 : 1000 }} animate={{ x: isActive ? 0 : 1000 }}
transition={{ duration: 0.5 }} transition={{ duration: 0.5 }}
> >
<div className="h-[calc(100%-4rem)] w-full mt-16 lg:h-full lg:mt-auto md:h-full md:mt-auto"> <div className="mt-16 h-[calc(100%-4rem)] w-full md:mt-auto md:h-full lg:mt-auto lg:h-full">
<div className="flex h-full w-full whitespace-nowrap" onClick={() => setIsActive(false)} > <div
className="flex h-full w-full"
onClick={() => setIsActive(false)}
>
<div className="flex w-full flex-col justify-evenly md:flex-row"> <div className="flex w-full flex-col justify-evenly md:flex-row">
<HeaderButton href="/games" Icon={HiOutlineCube} translationKey="header.games" /> <HeaderButton
<HeaderButton href="/settings" Icon={RxMixerVertical} translationKey="header.settings" /> href="/games"
<HeaderButton href="/discord" Icon={RiLinksFill} translationKey="header.discord" /> Icon={HiOutlineCube}
translationKey="header.games"
/>
<HeaderButton
href="/settings"
Icon={RxMixerVertical}
translationKey="header.settings"
/>
<HeaderButton
href="/discord"
Icon={RiLinksFill}
translationKey="header.discord"
/>
</div> </div>
</div> </div>
</div> </div>
</motion.div> </motion.div>
} )}
</div> </div>
); );
} }

View file

@ -12,12 +12,10 @@ export function HeaderButton(props: HeaderButtonProps) {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<Link <Link href={href} className="flex h-full w-full bg-navbar-color sm:h-auto">
href={href} <div className="group flex w-full flex-row items-center justify-center border-t-2 border-solid border-navbar-text-color p-4 md:border-none">
className="flex h-full w-full bg-navbar-color sm:h-auto">
<div className="group flex flex-row items-center justify-center p-4 w-full border-t-2 border-solid border-navbar-text-color md:border-none">
<Icon className="h-10 w-10 text-text-color transition duration-500 group-hover:text-text-hover-color md:h-6 md:w-6" /> <Icon className="h-10 w-10 text-text-color transition duration-500 group-hover:text-text-hover-color md:h-6 md:w-6" />
<span className="font-roboto pl-1 text-text-color text-4xl text-center font-bold transition duration-500 group-hover:text-text-hover-color md:text-lg"> <span className="font-roboto pl-1 text-center text-4xl font-bold text-text-color transition duration-500 group-hover:text-text-hover-color md:text-lg">
{t(translationKey)} {t(translationKey)}
</span> </span>
</div> </div>

View file

@ -2,10 +2,10 @@ import { Header } from "./Header";
export function HeaderRoute(props: { children: any }) { export function HeaderRoute(props: { children: any }) {
return ( return (
<div class="flex h-screen flex-col"> <div className="flex h-screen flex-col">
<Header /> <Header />
<div class="flex-1 bg-primary"> <div className="flex-1 bg-primary">
<main class="h-full">{props.children}</main> <main className="h-full">{props.children}</main>
</div> </div>
</div> </div>
); );

View file

@ -1,5 +1,9 @@
import { useState } from "preact/hooks"; import { useState, useEffect } from "preact/hooks";
import CryptoJS from "crypto-js";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { dec } from "../../aes";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import { Link } from "preact-router"; import { Link } from "preact-router";
import { RiPictureInPictureExitFill, RiFullscreenFill } from "react-icons/ri"; import { RiPictureInPictureExitFill, RiFullscreenFill } from "react-icons/ri";
import { import {
@ -8,6 +12,7 @@ import {
IoChevronForwardSharp, IoChevronForwardSharp,
IoReloadSharp IoReloadSharp
} from "react-icons/io5"; } from "react-icons/io5";
import { FaShareAlt } from "react-icons/fa";
import { FaXmark } from "react-icons/fa6"; import { FaXmark } from "react-icons/fa6";
interface ProxyFrame extends HTMLElement { interface ProxyFrame extends HTMLElement {
@ -15,10 +20,72 @@ interface ProxyFrame extends HTMLElement {
contentDocument: any; contentDocument: any;
} }
function Clipboard(text) {
var textarea = document.createElement("textarea"); // hacky
textarea.value = text;
document.body.appendChild(textarea);
textarea.select();
textarea.setSelectionRange(0, 99999);
document.execCommand("copy");
document.body.removeChild(textarea);
}
export function IframeHeader(props: { url: string }) { export function IframeHeader(props: { url: string }) {
const localProxy = localStorage.getItem("proxy") || "automatic";
const { t } = useTranslation(); const { t } = useTranslation();
const share = () => {
let proxyFrame: ProxyFrame | null = document.getElementById(
"iframe"
) as ProxyFrame;
if (localProxy === "ultraviolet" || localProxy === "automatic") {
var encodedUrl = proxyFrame.contentWindow.location.href
.replace(window.location.origin, "")
.replace(window.__uv$config.prefix, "");
//@ts-ignore
let decodedUrl = CryptoJS.AES.decrypt(
"U2FsdGVkX1" + encodedUrl,
location.origin + navigator.userAgent
).toString(CryptoJS.enc.Utf8);
Clipboard(decodedUrl);
toast(t("clipboard"));
} else {
toast("Your proxy choice doesn't support sharing.");
}
};
const [showPopout, setShowPopout] = useState(false); const [showPopout, setShowPopout] = useState(false);
const [showFullScreen, setFullScreen] = useState(false); const [showFullScreen, setFullScreen] = useState(false);
const [proxiedTitle, setProxiedTitle] = useState("");
const [proxiedFavicon, setProxiedFavicon] = useState("/generic_globe.png");
useEffect(() => {
const intervalFunction = () => {
let proxyFrame: ProxyFrame | null = document.getElementById(
"iframe"
) as ProxyFrame;
if (proxyFrame) {
let faviconLink =
proxyFrame.contentDocument.querySelector("link[rel*='icon']");
if (faviconLink) {
setProxiedFavicon(faviconLink.href);
} else {
setProxiedFavicon("/generic_globe.png");
}
setProxiedTitle(proxyFrame.contentDocument.title);
} else {
console.log(
"ehhh this aint supposed to happen. no proxied iframe found."
);
}
};
const intervalId = setInterval(intervalFunction, 1000);
return () => clearInterval(intervalId);
}, []);
if (showPopout) { if (showPopout) {
window.location.replace(props.url); window.location.replace(props.url);
@ -28,24 +95,21 @@ export function IframeHeader(props: { url: string }) {
setFullScreen(false); setFullScreen(false);
} }
return ( return (
<div>
<div <div
id="iframeNav" id="iframeNav"
className="flex h-16 flex-row items-center justify-between gap-3 bg-navbar-color px-4" className="flex h-16 flex-row items-center justify-between gap-3 bg-navbar-color px-4"
> >
<Link href="/" class="w-1/8"> <div className="w-1/8">
<div className="flex flex-row items-center"> <div className="flex flex-row items-center">
<img <img src={proxiedFavicon} className="h-12 w-12 p-2"></img>
src="/logo.png" <h1 className="font-roboto whitespace-normal text-sm font-bold text-text-color sm:visible sm:text-lg">
className="h-16 w-16 transition-all duration-1000 hover:rotate-[360deg]" {proxiedTitle ? proxiedTitle : "Loading..."}
alt="Nebula Logo"
></img>
<h1 className="font-roboto text-2xl font-bold text-navbar-text-color md:text-4xl">
{" "}
{t("header.title")}{" "}
</h1> </h1>
</div> </div>
</Link> </div>
<div className="flex flex-row items-center gap-3 md:gap-2"> <div id="navItems" className="w-1/8">
<div className="mr-4 flex flex-row items-center justify-end gap-3">
<IoChevronBackSharp <IoChevronBackSharp
className="duration-0500 h-6 w-6 cursor-pointer text-navbar-text-color transition-all hover:scale-110 hover:brightness-125" className="duration-0500 h-6 w-6 cursor-pointer text-navbar-text-color transition-all hover:scale-110 hover:brightness-125"
onClick={() => { onClick={() => {
@ -55,15 +119,6 @@ export function IframeHeader(props: { url: string }) {
proxyFrame.contentWindow.history.back(); proxyFrame.contentWindow.history.back();
}} }}
/> />
<IoReloadSharp
className="duration-0500 h-6 w-6 cursor-pointer text-navbar-text-color transition-all hover:rotate-[360deg] hover:scale-110 hover:brightness-125"
onClick={() => {
const proxyFrame: ProxyFrame | null = document.getElementById(
"iframe"
) as ProxyFrame;
proxyFrame.contentWindow.location.reload();
}}
/>
<IoChevronForwardSharp <IoChevronForwardSharp
className="duration-0500 h-6 w-6 cursor-pointer text-navbar-text-color transition-all hover:scale-110 hover:brightness-125" className="duration-0500 h-6 w-6 cursor-pointer text-navbar-text-color transition-all hover:scale-110 hover:brightness-125"
onClick={() => { onClick={() => {
@ -73,9 +128,19 @@ export function IframeHeader(props: { url: string }) {
proxyFrame.contentWindow.history.forward(); proxyFrame.contentWindow.history.forward();
}} }}
/> />
</div> <IoReloadSharp
<div id="navItems" class="w-1/8"> className="duration-0500 h-6 w-6 cursor-pointer text-navbar-text-color transition-all hover:rotate-[360deg] hover:scale-110 hover:brightness-125"
<div className="mr-4 flex flex-row items-center justify-end gap-3"> onClick={() => {
const proxyFrame: ProxyFrame | null = document.getElementById(
"iframe"
) as ProxyFrame;
proxyFrame.contentWindow.location.reload();
}}
/>
<FaShareAlt
className="duration-0500 h-6 w-6 cursor-pointer text-navbar-text-color transition-all hover:scale-110 hover:brightness-125"
onClick={share}
/>
<IoCodeSlashSharp <IoCodeSlashSharp
className="duration-0500 h-6 w-6 cursor-pointer text-navbar-text-color transition-all hover:scale-110 hover:brightness-125" className="duration-0500 h-6 w-6 cursor-pointer text-navbar-text-color transition-all hover:scale-110 hover:brightness-125"
onClick={() => { onClick={() => {
@ -97,7 +162,12 @@ export function IframeHeader(props: { url: string }) {
script.src = "https://cdn.jsdelivr.net/npm/eruda"; script.src = "https://cdn.jsdelivr.net/npm/eruda";
script.onload = function () { script.onload = function () {
if (!proxyWindow) return; if (!proxyWindow) return;
proxyWindow.eruda.init(); proxyWindow.eruda.init({
defaults: {
displaySize: 45,
theme: "Material Palenight"
}
});
proxyWindow.eruda.show(); proxyWindow.eruda.show();
}; };
proxyDocument.head.appendChild(script); proxyDocument.head.appendChild(script);
@ -118,5 +188,7 @@ export function IframeHeader(props: { url: string }) {
</div> </div>
</div> </div>
</div> </div>
<ToastContainer position="bottom-right" type="sucess" theme="dark" />
</div>
); );
} }

View file

@ -1,15 +1,25 @@
import { render } from "preact"; import { render } from "preact";
import { Suspense, lazy } from "preact/compat"; import { Suspense, lazy } from "preact/compat";
import { LoadSuspense } from "./LoadSuspense"; import { LoadSuspense } from "./LoadSuspense";
import { Helmet } from "react-helmet";
const Routes = lazy(() => import("./routes")); const Routes = lazy(() => import("./routes"));
const theme = localStorage.getItem("theme") || "main";
export default function App() { export default function App() {
return ( return (
<div>
<Helmet>
<link rel="stylesheet" href={"/themes/" + theme + ".css"}></link>
<link rel="stylesheet" href="/themes/main.css"></link>
</Helmet>
<Suspense fallback={<LoadSuspense />}> <Suspense fallback={<LoadSuspense />}>
<div> <div>
<Routes /> <Routes />
</div> </div>
</Suspense> </Suspense>
</div>
); );
} }

View file

@ -32,10 +32,7 @@
}, },
"languages": { "languages": {
"title": "Language", "title": "Language",
"subtitle": "Choose your preferred language", "subtitle": "Choose your preferred language"
"japanese": "Japanese",
"english": "English",
"spanish": "Spanish"
}, },
"proxymodes": { "proxymodes": {
"title": "Open in", "title": "Open in",
@ -46,11 +43,22 @@
}, },
"cloaking": { "cloaking": {
"title": "Cloaking", "title": "Cloaking",
"subtitle": "Choose how your tab looks" "subtitle": "Choose how your tab looks",
"aboutblank": "Open in about:blank"
}, },
"search": { "search": {
"title": "Search Engine", "title": "Search Engine",
"subtitle": "Choose your search engine" "subtitle": "Choose your search engine"
},
"bare": {
"title": "Bare Server",
"subtitle": "Enter the URL of your bare server",
"select": "Select"
},
"theme": {
"title": "Theme",
"subtitle": "Choose a theme so your eyes don't hate us",
"select": "Select"
} }
}, },
"titles": { "titles": {
@ -59,5 +67,14 @@
"discord": "Nebula - Discord", "discord": "Nebula - Discord",
"404": "Nebula - 404" "404": "Nebula - 404"
}, },
"comingsoon": "Coming soon!" "comingsoon": "Coming soon!",
"themes": {
"main": "Main",
"catppuccinMocha": "Catppuccin Mocha",
"catppuccinMacchiato": "Catppuccin Macchiato",
"catppuccinFrappe": "Catppuccin Frappe",
"catppuccinLatte": "Catppuccin Latte"
},
"clipboard": "URL copied to clipboard!",
"bareError": "That didn't quite work. Double check that the bare server exists and isn't blocked."
} }

View file

@ -32,10 +32,7 @@
}, },
"languages": { "languages": {
"title": "Idioma", "title": "Idioma",
"subtitle": "Elige tu idioma preferido", "subtitle": "Elige tu idioma preferido"
"japanese": "Japonés",
"english": "Inglés",
"spanish": "Español"
}, },
"proxymodes": { "proxymodes": {
"title": "Abrir en", "title": "Abrir en",
@ -46,11 +43,21 @@
}, },
"cloaking": { "cloaking": {
"title": "Encubrimiento", "title": "Encubrimiento",
"subtitle": "Elige cómo se ve tu pestaña" "subtitle": "Elige cómo se ve tu pestaña",
"aboutblank": "Abierte en about:blank"
}, },
"search": { "search": {
"title": "Buscador", "title": "Buscador",
"subtitle": "Elige tu motor de búsqueda." "subtitle": "Elige tu motor de búsqueda."
},
"bare": {
"title": "Bare Server",
"subtitle": "Pon tu url de tu bare server",
"select": "Seleccionar"
},
"theme": {
"title": "Mirar",
"subtitle": "Elige una mirada para que tus ojos no nos odienn"
} }
}, },
"titles": { "titles": {
@ -59,5 +66,14 @@
"discord": "Nebula - Discord", "discord": "Nebula - Discord",
"404": "Nebula - 404" "404": "Nebula - 404"
}, },
"comingsoon": "¡Próximamente!" "comingsoon": "¡Próximamente!",
"themes": {
"main": "Por defecto",
"catppuccinMocha": "Catppuccin Mocha",
"catppuccinMacchiato": "Catppuccin Macchiato",
"catppuccinFrappe": "Catppuccin Frappe",
"catppuccinLatte": "Catppuccin Latte"
},
"clipboard": "¡URL copiada al portapapeles!",
"bareError": "Esto no es funcional. Vuelva a verificar que el servidor bare exista y no esté bloqueado."
} }

View file

@ -1,6 +1,6 @@
{ {
"header": { "header": {
"title": "nebula.", "title": "ネブラ。",
"games": "ゲーム", "games": "ゲーム",
"settings": "セッティング", "settings": "セッティング",
"discord": "もっとリンクが欲しいですか?" "discord": "もっとリンクが欲しいですか?"
@ -32,10 +32,7 @@
}, },
"languages": { "languages": {
"title": "言語", "title": "言語",
"subtitle": "好きな言語を選んでください", "subtitle": "好きな言語を選んでください"
"japanese": "日本語",
"english": "英語",
"spanish": "スペイン語"
}, },
"proxymodes": { "proxymodes": {
"title": "開く", "title": "開く",
@ -46,11 +43,21 @@
}, },
"cloaking": { "cloaking": {
"title": "クローキング", "title": "クローキング",
"subtitle": "タブの見た目を選択する" "subtitle": "タブの見た目を選択する",
"aboutblank": "で開く about:blank"
}, },
"search": { "search": {
"title": "検索エンジン", "title": "検索エンジン",
"subtitle": "ネビュラの検索エンジンを選択してください" "subtitle": "ネビュラの検索エンジンを選択してください"
},
"bare": {
"title": "Bare サーバー",
"subtitle": "Bare サーバー URL を入力してください",
"select": "選択する"
},
"theme": {
"title": "テーマ",
"subtitle": "目が嫌いにならないようにテーマを選んでください"
} }
}, },
"titles": { "titles": {
@ -59,5 +66,14 @@
"discord": "ネブラ - Discord", "discord": "ネブラ - Discord",
"404": "ネブラ - 404" "404": "ネブラ - 404"
}, },
"comingsoon": "近日公開" "comingsoon": "近日公開",
"themes": {
"main": "デフォルト",
"catppuccinMocha": "Catppuccin Mocha",
"catppuccinMacchiato": "Catppuccin Macchiato",
"catppuccinFrappe": "Catppuccin Frappe",
"catppuccinLatte": "Catppuccin Latte"
},
"clipboard": "URL がクリップボードにコピーされました!",
"bareError": "それはうまくいきませんでした。Bare サーバーが存在し、ブロックされていないことを再確認してください。"
} }

View file

@ -1,13 +1,91 @@
import { useState } from "preact/hooks"; import { useState } from "preact/hooks";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { HeaderRoute } from "../components/HeaderRoute"; import { HeaderRoute } from "../components/HeaderRoute";
import { set } from "../util/IDB";
import { uninstallServiceWorkers } from "../util/SWHelper";
import prod from "./config.json"; // Set prod to true if you wish to load balance
import { enc } from "../aes"; import { enc } from "../aes";
import CloakedHead from "../util/CloakedHead"; import CloakedHead from "../util/CloakedHead";
import { useEffect } from "preact/hooks";
export function Home() { export function Home() {
const [isFocused, setIsFocused] = useState(false); const [isFocused, setIsFocused] = useState(false);
const [showSuggestions, setShowSuggestions] = useState(false);
const [inputValue, setInputValue] = useState(""); const [inputValue, setInputValue] = useState("");
const [suggestions, setSuggestions] = useState([]);
useEffect(() => {
const handleLoad = () => {
const firstLoad = localStorage.getItem("firstLoad") || "true";
console.log(firstLoad);
if (firstLoad == "true" && prod) {
function changeBare(url: string) {
set("bare", url);
localStorage.setItem("bare", url);
uninstallServiceWorkers();
window.location.reload();
}
async function test() {
const nonProtocolOrigin = window.location.origin.replace(
/^https?:\/\//,
""
);
// Do Tokyo-US pinging to find optimal server
const ping = async (url: string) => {
let start = Date.now();
await fetch(url);
let end = Date.now();
let total = end - start;
return total;
};
const usUrl = "https://us." + nonProtocolOrigin;
const jpUrl = "https://jp." + nonProtocolOrigin;
console.log(usUrl, jpUrl)
const [usTime, jpTime] = await Promise.all([
ping(usUrl),
ping(jpUrl)
]);
if (usTime < jpTime) {
console.log("US faster");
changeBare(usUrl);
} else {
console.log("Japan faster");
changeBare(jpUrl);
}
localStorage.setItem("firstLoad", "false");
}
test();
}
};
window.addEventListener("load", handleLoad);
return () => window.removeEventListener("load", handleLoad);
}, []);
const { t } = useTranslation(); const { t } = useTranslation();
const handleInputChange = async (event) => {
setInputValue((event.target as HTMLInputElement).value);
const newQuery = event.target.value;
setInputValue(newQuery);
const response = await fetch(`/search=${newQuery}`).then((res) =>
res.json()
);
const newSuggestions = response?.map((item) => item.phrase) || [];
setSuggestions(newSuggestions);
};
const handleSubmit = (event) => { const handleSubmit = (event) => {
event.preventDefault(); event.preventDefault();
window.location.href = window.location.href =
@ -27,36 +105,80 @@ export function Home() {
originalTitle={t("titles.home")} originalTitle={t("titles.home")}
originalFavicon="/logo.png" originalFavicon="/logo.png"
/> />
<div class="flex h-full flex-col items-center justify-center"> <div className="flex h-full flex-col items-center justify-center">
<div class="font-inter absolute bottom-0 left-0 p-4 text-sm italic text-input-text"> <div className="font-inter absolute bottom-0 left-0 p-4 text-sm italic text-input-text">
Nebula &copy; Nebula Services {new Date().getUTCFullYear()} Nebula &copy; Nebula Services {new Date().getUTCFullYear()}
</div> </div>
<a href="https://github.com/NebulaServices/Nebula"> <a href="https://github.com/NebulaServices/Nebula">
<div class="font-inter absolute bottom-0 right-0 p-4 text-sm text-input-text"> <div className="font-inter absolute bottom-0 right-0 p-4 text-sm text-input-text">
GitHub GitHub
</div> </div>
</a> </a>
<form <form
onSubmit={handleSubmit} onSubmit={handleSubmit}
class="flex h-full w-full items-center justify-center" className="flex h-full w-full flex-col items-center justify-center"
> >
<input <input
onFocus={() => { onFocus={() => {
setShowSuggestions(true);
setIsFocused(true); setIsFocused(true);
}} }}
onBlur={() => { onBlur={() => {
setIsFocused(false); setIsFocused(false);
setTimeout(() => {
setShowSuggestions(false); // delay so the user has time to click suggestions
}, 200);
}} }}
type="text" type="text"
value={inputValue} value={inputValue}
onChange={(e) => onChange={handleInputChange}
setInputValue((e.target as HTMLInputElement).value) className={`font-roboto h-14 rounded-t-2xl border border-input-border-color bg-input p-2 text-center text-xl text-input-text placeholder:text-input-text focus:outline-none ${
} isFocused && inputValue.trim() !== ""
className={`font-roboto h-14 rounded-2xl border border-input-border-color bg-input p-2 text-center text-xl placeholder:text-input-text focus:outline-none ${ ? "w-10/12 md:w-3/12"
isFocused ? "w-10/12 md:w-3/12" : "w-80" : "w-80 rounded-2xl"
} transition-all duration-300`} } transition-all duration-300`}
placeholder={isFocused ? "" : t("home.placeholder")} placeholder={isFocused ? "" : t("home.placeholder")}
/> />
<div className="relative flex w-10/12 flex-col items-center md:w-3/12">
<div className="absolute w-full text-center">
{showSuggestions &&
suggestions.map((suggestion, index) => (
<a
href={
"/go/" +
encodeURIComponent(
//@ts-ignore
enc(
suggestion,
window.location.origin.slice(8) + navigator.userAgent
).substring(10)
)
}
>
<div
className={`font-roboto w-110 flex h-10 flex-none shrink-0 items-center justify-center border border-input-border-color bg-input p-2 text-xl hover:bg-dropdown-option-hover-color ${
index === suggestions.length - 1 ? "rounded-b-2xl" : ""
}`}
key={index}
>
{suggestion}
</div>
</a>
))}
{/* {showSuggestions &&
Array.from({ length: 10 }, (_, index) => (
<div
key={index}
className="font-roboto w-110 hover:bg-dropdown-option-hover-colo flex h-8 flex-none shrink-0 items-center justify-center border border-input-border-color p-2 text-2xl"
>
Example suggestion
</div>
))}
*/}
</div>
</div>
</form> </form>
</div> </div>
</HeaderRoute> </HeaderRoute>

View file

@ -22,7 +22,7 @@ export function ProxyFrame(props: { url: string }) {
const localProxy = localStorage.getItem("proxy") || "automatic"; const localProxy = localStorage.getItem("proxy") || "automatic";
const proxyMode = localStorage.getItem("proxyMode") || "embed"; const proxyMode = localStorage.getItem("proxyMode") || "embed";
const searchEngine = const searchEngine =
localStorage.getItem("searchEngine") || "https://google.com/search?q=%s"; localStorage.getItem("searchEngine") || "https://duckduckgo.com/?q=%s";
const [ProxiedUrl, setProxiedUrl] = useState<string | undefined>(undefined); const [ProxiedUrl, setProxiedUrl] = useState<string | undefined>(undefined);
//@ts-ignore //@ts-ignore
@ -47,7 +47,9 @@ export function ProxyFrame(props: { url: string }) {
window.__uv$config.encodeUrl(decodedUrl); window.__uv$config.encodeUrl(decodedUrl);
} else if (localProxy === "dynamic") { } else if (localProxy === "dynamic") {
result = result =
window.__dynamic$config.prefix + encodeURIComponent(decodedUrl); window.__dynamic$config.prefix +
"route?url=" +
encodeURIComponent(decodedUrl);
} else { } else {
// automatic. use SiteSupport.json to determine proxy support // automatic. use SiteSupport.json to determine proxy support
const matchingKey = Object.keys(SiteSupport).find((key) => const matchingKey = Object.keys(SiteSupport).find((key) =>
@ -60,7 +62,9 @@ export function ProxyFrame(props: { url: string }) {
window.__uv$config.encodeUrl(decodedUrl); window.__uv$config.encodeUrl(decodedUrl);
} else if (SiteSupport[matchingKey] === "dynamic") { } else if (SiteSupport[matchingKey] === "dynamic") {
result = result =
window.__dynamic$config.prefix + encodeURIComponent(decodedUrl); window.__dynamic$config.prefix +
"route?url=" +
encodeURIComponent(decodedUrl);
} else if (SiteSupport[matchingKey] === "rammerhead") { } else if (SiteSupport[matchingKey] === "rammerhead") {
result = await RammerheadEncode(decodedUrl); result = await RammerheadEncode(decodedUrl);
} else { } else {
@ -93,8 +97,12 @@ export function ProxyFrame(props: { url: string }) {
window.location.href = ProxiedUrl; window.location.href = ProxiedUrl;
} }
if (proxyMode === "embed") {
history.pushState({}, "", "/");
}
return ( return (
<div class="h-screen w-screen bg-primary"> <div className="h-screen w-screen bg-primary">
<CloakedHead <CloakedHead
originalTitle={t("titles.home")} originalTitle={t("titles.home")}
originalFavicon="/logo.png" originalFavicon="/logo.png"

View file

@ -1,9 +1,17 @@
import { HeaderRoute } from "../components/HeaderRoute"; import { HeaderRoute } from "../components/HeaderRoute";
interface Window {
__uv$config: any;
}
export function Radon() { export function Radon() {
return ( return (
<HeaderRoute> <HeaderRoute>
<iframe src="/~/uv/https%3A%2F%2Fradon.games%2F" class="w-full h-full"></iframe> <iframe
</HeaderRoute> src={
) window.__uv$config.prefix +
window.__uv$config.encodeUrl("https://radon.games")
}
className="h-full w-full"
></iframe>
</HeaderRoute>
);
} }

View file

@ -0,0 +1,84 @@
import { useState, useEffect } from "preact/hooks";
import { set } from "../../util/IDB";
import { uninstallServiceWorkers } from "../../util/SWHelper";
import { useTranslation } from "react-i18next";
import { ToastContainer, toast } from "react-toastify";
import { BareTest } from "./BareTest";
interface BareInputProps {
placeholder: string;
storageKey: string;
}
function BareInput(props: BareInputProps) {
const { t } = useTranslation();
const value = localStorage.getItem(props.storageKey) || "/bare/";
const [inputValue, setInputValue] = useState(value);
function validateUrl(url: string) {
let finalUrl = url;
if (url === "/bare/" || url === "/bare") {
finalUrl = "/bare/";
return finalUrl;
}
if (url === null || url === undefined || url === "") {
finalUrl = "/bare/";
return finalUrl;
}
if (!url.endsWith("/")) {
finalUrl = url + "/";
}
if (!finalUrl.startsWith("http://") && !finalUrl.startsWith("https://")) {
finalUrl = "https://" + finalUrl;
}
return finalUrl;
}
function handleChange() {
const url = validateUrl(
(document.getElementById("input") as HTMLInputElement).value
);
BareTest(url + "v3/").then((result) => {
if (result) {
setInputValue(
(document.getElementById("input") as HTMLInputElement).value
);
set(props.storageKey, url);
localStorage.setItem(props.storageKey, url);
uninstallServiceWorkers();
window.location.reload();
} else {
(document.getElementById("input") as HTMLInputElement).value =
localStorage.getItem("bare") || "/bare/";
toast(t("bareError"), {
type: "error"
});
}
});
}
return (
<div>
<ToastContainer position="bottom-right" theme="dark" />
<div className="flex flex-col items-center">
<input
type="text"
placeholder={props.placeholder}
value={inputValue}
onKeyPress={(event) => {
if (event.key === "Enter") {
handleChange()
}
}}
id="input"
className="font-roboto flex h-14 w-56 flex-row rounded-2xl border border-input-border-color bg-input p-4 text-center text-xl"
/>
<div
className="font-roboto mt-2 flex h-4 w-36 cursor-pointer flex-row items-center justify-center rounded-xl border border-input-border-color bg-input p-5 text-center text-lg"
onClick={handleChange}
>
{t("settings.bare.select")}
</div>
</div>
</div>
);
}
export default BareInput;

View file

@ -0,0 +1,29 @@
export function BareTest(bareUrl) {
const headers = new Headers({
"x-bare-url": "https://www.google.com",
"X-Bare-Headers": JSON.stringify({
Accept:
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
})
});
return fetch(bareUrl, {
method: "GET",
headers: headers
})
.then((response) => {
if (
response.headers.get("x-bare-status") === "200" ||
response.headers.get("x-bare-status") === "302"
) {
return true;
} else {
// the site is a real site but doesn't act like a bare server
return false;
}
})
.catch((error) => {
// incase the site doesn't exist
return false;
});
}

View file

@ -17,11 +17,11 @@ const CloakPreset = (props: Props) => {
return ( return (
<div <div
onClick={cloak} onClick={cloak}
class="cursor-pointer rounded-full border border-input-border-color bg-lighter" className="cursor-pointer rounded-full border border-input-border-color bg-lighter"
> >
<img <img
src={props.faviconUrl === "none" ? "/logo.png" : props.faviconUrl} src={props.faviconUrl === "none" ? "/logo.png" : props.faviconUrl}
class="h-16 w-16 p-4" className="h-16 w-16 p-4"
/> />
</div> </div>
); );

View file

@ -1,9 +1,19 @@
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import { tabContentVariant, settingsPageVariant } from "./Variants"; import { tabContentVariant, settingsPageVariant } from "./Variants";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import Dropdown from "./Dropdown";
function Customization({ id, active }) { function Customization({ id, active }) {
const { t } = useTranslation(); const { t } = useTranslation();
const themes = [
{ id: "main", label: t("themes.main") },
{ id: "catppuccinMocha", label: t("themes.catppuccinMocha") },
{ id: "catppuccinMacchiato", label: t("themes.catppuccinMacchiato") },
{ id: "catppuccinFrappe", label: t("themes.catppuccinFrappe") },
{ id: "catppuccinLatte", label: t("themes.catppuccinLatte") }
];
return ( return (
<motion.div <motion.div
role="tabpanel" role="tabpanel"
@ -17,8 +27,15 @@ function Customization({ id, active }) {
variants={settingsPageVariant} variants={settingsPageVariant}
className="content-card flex w-full flex-col items-center justify-center text-center" className="content-card flex w-full flex-col items-center justify-center text-center"
> >
<img src="/comingsoonsnake.png" class="h-72 w-72"></img> <div className="flex h-64 w-80 flex-col flex-wrap content-center items-center rounded-lg border border-input-border-color bg-lighter p-2 text-center">
<h1 class="font-roboto text-3xl">{t("comingsoon")}</h1> <div className="p-2 text-3xl font-bold text-input-text">
{t("settings.theme.title")}
</div>
<div className="text-md p-4 font-bold text-input-text">
{t("settings.theme.subtitle")}
</div>
<Dropdown storageKey="theme" options={themes} refresh={true} />
</div>
</motion.div> </motion.div>
</motion.div> </motion.div>
); );

View file

@ -35,11 +35,11 @@ const Dropdown = ({
onClick={() => setIsOpen(!isOpen)} onClick={() => setIsOpen(!isOpen)}
> >
<div className="flex h-full w-full select-none flex-row items-center"> <div className="flex h-full w-full select-none flex-row items-center">
<div class="h-full w-1/4"></div> <div className="h-full w-1/4"></div>
<div class="flex w-2/4 flex-col items-center"> <div className="flex w-2/4 flex-col items-center text-input-text">
{options.find((o) => o.id === choice)?.label} {options.find((o) => o.id === choice)?.label}
</div> </div>
<div class="flex w-1/4 flex-col items-center"> <div className="flex w-1/4 flex-col items-center text-input-text">
<FaAngleDown /> <FaAngleDown />
</div> </div>
</div> </div>
@ -48,7 +48,7 @@ const Dropdown = ({
{options.map((option, index) => ( {options.map((option, index) => (
<div <div
key={option.id} key={option.id}
className={`border border-input-border-color bg-input p-2 hover:bg-dropdown-option-hover-color ${ className={`border border-input-border-color bg-input p-2 text-input-text hover:bg-dropdown-option-hover-color ${
index === options.length - 1 ? "rounded-b-2xl" : "" index === options.length - 1 ? "rounded-b-2xl" : ""
}`} }`}
onClick={() => { onClick={() => {

View file

@ -7,9 +7,9 @@ const Misc = ({ id, active }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const languages = [ const languages = [
{ id: "en-US", label: t("settings.languages.english") }, { id: "en-US", label: "English" },
{ id: "es", label: t("settings.languages.spanish") }, { id: "es", label: "Español" },
{ id: "ja", label: t("settings.languages.japanese") } { id: "ja", label: "日本語" }
]; ];
return ( return (
@ -23,11 +23,15 @@ const Misc = ({ id, active }) => {
> >
<motion.div <motion.div
variants={settingsPageVariant} variants={settingsPageVariant}
className="content-card flex flex-row flex-wrap justify-center w-full gap-4" className="content-card flex w-full flex-row flex-wrap justify-center gap-4"
> >
<div class="flex h-64 w-80 flex-col flex-wrap content-center items-center rounded-lg border border-input-border-color bg-lighter p-7 text-center"> <div className="flex h-64 w-80 flex-col flex-wrap content-center items-center rounded-lg border border-input-border-color bg-lighter p-7 text-center">
<div class="text-3xl">{t("settings.languages.title")}</div> <div className="text-3xl font-bold text-input-text">
<div class="text-md">{t("settings.languages.subtitle")}</div> {t("settings.languages.title")}
</div>
<div className="text-md font-bold text-input-text">
{t("settings.languages.subtitle")}
</div>
<Dropdown <Dropdown
storageKey="i18nextLng" storageKey="i18nextLng"
options={languages} options={languages}

View file

@ -1,6 +1,7 @@
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import { tabContentVariant, settingsPageVariant } from "./Variants"; import { tabContentVariant, settingsPageVariant } from "./Variants";
import Dropdown from "./Dropdown"; import Dropdown from "./Dropdown";
import BareInput from "./BareInput";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
const Proxy = ({ id, active }) => { const Proxy = ({ id, active }) => {
@ -20,9 +21,9 @@ const Proxy = ({ id, active }) => {
]; ];
const searchEngines = [ const searchEngines = [
{ id: "https://duckduckgo.com/?q=%s", label: "DuckDuckGo" },
{ id: "https://google.com/search?q=%s", label: "Google" }, { id: "https://google.com/search?q=%s", label: "Google" },
{ id: "https://bing.com/search?q=%s", label: "Bing" }, { id: "https://bing.com/search?q=%s", label: "Bing" }
{ id: "https://duckduckgo.com/?q=%s", label: "DuckDuckGo" }
]; ];
return ( return (
@ -38,29 +39,50 @@ const Proxy = ({ id, active }) => {
variants={settingsPageVariant} variants={settingsPageVariant}
className="content-card flex w-full flex-row flex-wrap justify-center gap-4" className="content-card flex w-full flex-row flex-wrap justify-center gap-4"
> >
<div class="flex h-64 w-80 flex-col flex-wrap content-center items-center rounded-lg border border-input-border-color bg-lighter p-7 text-center"> <div className="flex h-64 w-80 flex-col flex-wrap content-center items-center rounded-lg border border-input-border-color bg-lighter p-2 text-center">
<div class="p-2 text-3xl">{t("settings.proxy.title")}</div> <div className="p-2 text-3xl font-bold text-input-text">
<div class="text-md p-4">{t("settings.proxy.subtitle")}</div> {t("settings.proxy.title")}
</div>
<div className="text-md p-4 font-bold text-input-text">
{t("settings.proxy.subtitle")}
</div>
<Dropdown storageKey="proxy" options={engines} refresh={false} /> <Dropdown storageKey="proxy" options={engines} refresh={false} />
</div> </div>
<div class="flex h-64 w-80 flex-col flex-wrap content-center items-center rounded-lg border border-input-border-color bg-lighter p-7 text-center"> <div className="flex h-64 w-80 flex-col flex-wrap content-center items-center rounded-lg border border-input-border-color bg-lighter p-2 text-center">
<div class="p-2 text-3xl">{t("settings.proxymodes.title")}</div> <div className="p-2 text-3xl font-bold text-input-text">
<div class="text-md p-4">{t("settings.proxymodes.subtitle")}</div> {t("settings.proxymodes.title")}
</div>
<div className="text-md p-4 font-bold text-input-text">
{t("settings.proxymodes.subtitle")}
</div>
<Dropdown <Dropdown
storageKey="proxyMode" storageKey="proxyMode"
options={proxyModes} options={proxyModes}
refresh={false} refresh={false}
/> />
</div> </div>
<div class="flex h-64 w-80 flex-col flex-wrap content-center items-center rounded-lg border border-input-border-color bg-lighter p-7 text-center"> <div className="flex h-64 w-80 flex-col flex-wrap content-center items-center rounded-lg border border-input-border-color bg-lighter p-2 text-center">
<div class="p-2 text-3xl">{t("settings.search.title")}</div> <div className="p-2 text-3xl font-bold text-input-text">
<div class="text-md p-4">{t("settings.search.subtitle")}</div> {t("settings.search.title")}
</div>
<div className="text-md p-4 font-bold text-input-text">
{t("settings.search.subtitle")}
</div>
<Dropdown <Dropdown
storageKey="searchEngine" storageKey="searchEngine"
options={searchEngines} options={searchEngines}
refresh={false} refresh={false}
/> />
</div> </div>
<div className="flex h-64 w-80 flex-col flex-wrap content-center items-center rounded-lg border border-input-border-color bg-lighter p-2 text-center">
<div className="p-2 text-3xl font-bold text-input-text">
{t("settings.bare.title")}
</div>
<div className="text-md p-4 font-bold text-input-text">
{t("settings.bare.subtitle")}
</div>
<BareInput placeholder="/bare/" storageKey="bare" />
</div>
</motion.div> </motion.div>
</motion.div> </motion.div>
); );

View file

@ -69,14 +69,17 @@ const TabComponent = ({ tabs, defaultIndex = 0 }) => {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div class="flex h-full w-full flex-col items-center"> <div className="flex h-full w-full flex-col items-center">
<div className="container h-full w-full"> <div className="container h-full w-full">
<div className="tabs-component"> <div className="tabs-component">
<ul className="tab-links" role="tablist"> <ul className="tab-links" role="tablist">
{tabs.map((tab, index) => ( {tabs.map((tab, index) => (
<motion.li <motion.li
key={tab.id} key={tab.id}
className={cn("tab", { active: activeTabIndex === index })} className={
"flex h-12 flex-row " +
cn("tab", { active: activeTabIndex === index })
}
role="presentation" role="presentation"
variants={tabVariant} variants={tabVariant}
animate={activeTabIndex === index ? "active" : "inactive"} animate={activeTabIndex === index ? "active" : "inactive"}

View file

@ -2,6 +2,7 @@ import { motion } from "framer-motion";
import { tabContentVariant, settingsPageVariant } from "./Variants"; import { tabContentVariant, settingsPageVariant } from "./Variants";
import CloakPreset from "./CloakPreset"; import CloakPreset from "./CloakPreset";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { LoadSuspense } from "../../LoadSuspense";
const TabSettings = ({ id, active }) => { const TabSettings = ({ id, active }) => {
const { t } = useTranslation(); const { t } = useTranslation();
@ -19,9 +20,13 @@ const TabSettings = ({ id, active }) => {
variants={settingsPageVariant} variants={settingsPageVariant}
className="content-card flex w-full flex-col items-center justify-center text-center" className="content-card flex w-full flex-col items-center justify-center text-center"
> >
<div class="text-3xl">{t("settings.cloaking.title")}</div> <div className="text-3xl font-bold text-input-text">
<div class="text-md pb-5">{t("settings.cloaking.subtitle")}</div> {t("settings.cloaking.title")}
<div class="flex flex-row space-x-4"> </div>
<div className="text-md pb-5 font-bold text-input-text">
{t("settings.cloaking.subtitle")}
</div>
<div className="flex flex-row space-x-4">
<CloakPreset faviconUrl="none" title="none" /> <CloakPreset faviconUrl="none" title="none" />
<CloakPreset <CloakPreset
faviconUrl="https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http://google.com&size=32" faviconUrl="https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http://google.com&size=32"
@ -39,6 +44,40 @@ const TabSettings = ({ id, active }) => {
faviconUrl="https://ssl.gstatic.com/classroom/ic_product_classroom_144.png" faviconUrl="https://ssl.gstatic.com/classroom/ic_product_classroom_144.png"
title="Home" title="Home"
/> />
<CloakPreset
faviconUrl="https://asset-cdn.schoology.com/sites/all/themes/schoology_theme/favicon.ico"
title="Schoology"
/>
</div>
<div className="relative p-4">
<button
className="font-roboto h-14 w-56 rounded-2xl border border-input-border-color bg-input p-2 text-center text-xl font-bold text-input-text placeholder:text-input-text focus:outline-none"
onClick={() => {
let newWindow = window.open("about:blank");
let iframe = document.createElement("iframe");
iframe.src = window.location.origin;
iframe.style.width = "100%";
iframe.style.height = "100%";
iframe.style.border = "none";
iframe.style.overflow = "hidden";
iframe.style.margin = "0";
iframe.style.padding = "0";
iframe.style.position = "fixed";
iframe.style.top = "0";
iframe.style.bottom = "0";
iframe.style.left = "0";
iframe.style.right = "0";
newWindow.document.body.appendChild(iframe);
window.location.replace("https://google.com");
return (
<div>
<LoadSuspense />
</div>
);
}}
>
{t("settings.cloaking.aboutblank")}
</button>
</div> </div>
</motion.div> </motion.div>
</motion.div> </motion.div>

View file

@ -1,3 +1,4 @@
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap");
* { * {
box-sizing: border-box; box-sizing: border-box;
} }
@ -11,7 +12,7 @@
body { body {
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
font-family: Arial, Helvetica, sans-serif; font-family: Roboto;
background: var(--active-color); background: var(--active-color);
transition: background 1.5s ease; transition: background 1.5s ease;
} }
@ -62,7 +63,7 @@ img {
height: 30px; height: 30px;
width: 30px; width: 30px;
min-width: 30px; min-width: 30px;
fill: var(--black); fill: var(--tab-color);
transition: fill 0.5s ease; transition: fill 0.5s ease;
} }

View file

@ -12,15 +12,15 @@ export function NotFound() {
originalTitle={t("titles.404")} originalTitle={t("titles.404")}
originalFavicon="/logo.png" originalFavicon="/logo.png"
/> />
<section class="h-full"> <section className="h-full">
<div class="flex h-full flex-col items-center justify-center"> <div className="flex h-full flex-col items-center justify-center">
<img src="/404.png" class="h-72"></img> <img src="/404.png" className="h-72"></img>
<div class="flex flex-col items-center p-6"> <div className="flex flex-col items-center p-6">
<p class="font-roboto text-4xl font-bold">{t("404.text")}</p> <p className="font-roboto text-4xl font-bold">{t("404.text")}</p>
<span class="font-roboto text-3xl">404</span> <span className="font-roboto text-3xl">404</span>
</div> </div>
<Link href="/"> <Link href="/">
<button class="font-roboto h-14 w-44 rounded-2xl border border-input-border-color bg-input p-2 text-center text-xl placeholder:text-input-text focus:outline-none"> <button className="font-roboto h-14 w-44 rounded-2xl border border-input-border-color bg-input p-2 text-center text-xl placeholder:text-input-text focus:outline-none">
{t("404.return")} {t("404.return")}
</button> </button>
</Link> </Link>

3
src/pages/config.json Normal file
View file

@ -0,0 +1,3 @@
{
"prod": false
}

View file

@ -11,23 +11,31 @@ export function DiscordPage() {
originalTitle={t("titles.discord")} originalTitle={t("titles.discord")}
originalFavicon="/logo.png" originalFavicon="/logo.png"
/> />
<section class="h-full"> <section className="h-full">
<div class="flex h-full flex-col items-center justify-center"> <div className="flex h-full flex-col items-center justify-center">
<img src="/services.png" class="h-72 w-72"></img> <img src="/services.png" className="h-72 w-72"></img>
<div class="flex flex-col items-center p-6"> <div className="flex flex-col items-center p-6">
<p class="font-roboto text-4xl font-bold">{t("discord.title")}</p> <p className="font-roboto text-4xl font-bold text-input-text">
<span class="font-roboto text-3xl">{t("discord.sub")}</span> {t("discord.title")}
</p>
<span className="font-roboto text-3xl text-input-text">
{t("discord.sub")}
</span>
</div> </div>
<a href="https://discord.gg/unblocker" class="p-6"> <a href="https://discord.gg/unblocker" className="p-6">
<button class="font-roboto h-14 w-56 rounded-2xl border border-input-border-color bg-input p-2 text-center text-xl placeholder:text-input-text focus:outline-none"> <button className="font-roboto h-14 w-56 rounded-2xl border border-input-border-color bg-input p-2 text-center text-xl text-input-text placeholder:text-input-text focus:outline-none">
{t("discord.button1")} {t("discord.button1")}
</button> </button>
</a> </a>
<a <a
href="/~/uv/https%3A%2F%2Fdiscord.com%2Finvite%2Funblocker" onClick={() => {
class="p-6" window.location.href =
window.__uv$config.prefix +
window.__uv$config.encodeUrl("https://discord.gg/unblocker");
}}
className="p-6"
> >
<button class="font-roboto h-14 w-56 rounded-2xl border border-input-border-color bg-input p-2 text-center text-xl placeholder:text-input-text focus:outline-none"> <button className="font-roboto h-14 w-56 rounded-2xl border border-input-border-color bg-input p-2 text-center text-xl text-input-text placeholder:text-input-text focus:outline-none">
{t("discord.button2")} {t("discord.button2")}
</button> </button>
</a> </a>

View file

@ -6,8 +6,8 @@ import { ProxyFrame } from "./pages/ProxyFrame.js";
import { Radon } from "./pages/Radon"; import { Radon } from "./pages/Radon";
import { Settings } from "./pages/Settings/"; import { Settings } from "./pages/Settings/";
import { AboutBlank } from "./AboutBlank"; import { AboutBlank } from "./AboutBlank";
import "./style.css"; import "./style.css";
import "./themes/main.css";
import "./i18n"; import "./i18n";
export default function Routes() { export default function Routes() {
@ -25,4 +25,3 @@ export default function Routes() {
</LocationProvider> </LocationProvider>
); );
} }

22
src/util/IDB.js Normal file
View file

@ -0,0 +1,22 @@
function set(key, value) {
localforage.config({
driver: localforage.INDEXEDDB,
name: "Nebula",
version: 1.0,
storeName: "nebula_config",
description: "Nebula Config for things reliant on IndexedDB"
});
localforage.setItem(key, value);
}
async function get(key) {
localforage.config({
driver: localforage.INDEXEDDB,
name: "Nebula",
version: 1.0,
storeName: "nebula_config",
description: "Nebula Config for things reliant on IndexedDB"
});
return await localforage.getItem(key);
}
export { set, get };

19
src/util/SWHelper.js Normal file
View file

@ -0,0 +1,19 @@
function updateServiceWorkers() {
navigator.serviceWorker.getRegistrations().then(function (registrations) {
for (let registration of registrations) {
registration.update();
console.log("Service Worker Updated");
}
});
}
function uninstallServiceWorkers() {
navigator.serviceWorker.getRegistrations().then(function (registrations) {
for (let registration of registrations) {
registration.unregister();
console.log("Service Worker Unregistered");
}
});
}
export { updateServiceWorkers, uninstallServiceWorkers };

View file

@ -5,6 +5,6 @@
"example.com": "ultraviolet", "example.com": "ultraviolet",
"spotify.com": "dynamic", "spotify.com": "dynamic",
"spotify.link": "dynamic", "spotify.link": "dynamic",
"youtube.com": "dynamic", "youtube.com": "ultraviolet",
"youtu.be": "dynamic" "youtu.be": "ultraviolet"
} }

View file

@ -6,6 +6,7 @@
"noEmit": true, "noEmit": true,
"jsx": "react-jsx", "jsx": "react-jsx",
"jsxImportSource": "preact", "jsxImportSource": "preact",
"esModuleInterop": true,
"skipLibCheck": true, "skipLibCheck": true,
"paths": {} "paths": {}
} }

View file

@ -2,7 +2,12 @@ import million from "million/compiler";
import { defineConfig } from "vite"; import { defineConfig } from "vite";
import preact from "@preact/preset-vite"; import preact from "@preact/preset-vite";
import { viteStaticCopy } from "vite-plugin-static-copy"; import { viteStaticCopy } from "vite-plugin-static-copy";
import { uvPath } from "@titaniumnetwork-dev/ultraviolet"; import { uvPath } from "@nebula-services/ultraviolet";
import { dynamicPath } from "@nebula-services/dynamic";
import path from "path";
const __dirname = path.resolve();
console.log(dynamicPath);
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
@ -13,6 +18,20 @@ export default defineConfig({
src: `${uvPath}/uv.*.js`.replace(/\\/g, "/"), src: `${uvPath}/uv.*.js`.replace(/\\/g, "/"),
dest: "uv", dest: "uv",
overwrite: false overwrite: false
},
{
// .replace fixes weird paths on Windows
src: `${dynamicPath}/dynamic.*.js`.replace(/\\/g, "/"),
dest: "dynamic",
overwrite: false
},
{
src: `${__dirname}/node_modules/localforage/dist/localforage.*.js`.replace(
/\\/g,
"/"
),
dest: "localforage",
overwrite: false
} }
] ]
}), }),