+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/[lang]/settings/pr.astro b/src/pages/[lang]/settings/pr.astro
new file mode 100644
index 00000000..a669605b
--- /dev/null
+++ b/src/pages/[lang]/settings/pr.astro
@@ -0,0 +1,195 @@
+---
+import InstalledPlugins from "@components/catalog/InstalledPlugins.svelte";
+import SettingsCard from "@components/settings/SettingsCard.astro";
+import Toast from "@components/toasts/Toast.svelte";
+import ToastWrapper from "@components/toasts/ToastWrapper.svelte";
+import Layout from "@layouts/Layout.astro";
+import SettingsLayout from "@layouts/SettingsLayout.astro";
+import SettingsSection from "@layouts/SettingsSection.astro";
+import { Icon } from "astro-icon/components";
+import { getLangFromUrl, useTranslations } from "../../../i18n/utils";
+
+const lang = getLangFromUrl(Astro.url);
+const t = useTranslations(lang);
+export function getStaticPaths() {
+ const STATIC_PATHS = [{ params: { lang: "en_US" } }, { params: { lang: "jp" } }];
+ return STATIC_PATHS;
+}
+export const prerender = true;
+import { MARKETPLACE_ENABLED } from "astro:env/client";
+---
+
+
+
+
+
+
+
+
+
+
+
+
+ {MARKETPLACE_ENABLED &&
+
+
+
+ }
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/[lang]/settings/tab.astro b/src/pages/[lang]/settings/tab.astro
new file mode 100644
index 00000000..dbf5d1a3
--- /dev/null
+++ b/src/pages/[lang]/settings/tab.astro
@@ -0,0 +1,81 @@
+---
+import SettingsCard from "@components/settings/SettingsCard.astro";
+import Toast from "@components/toasts/Toast.svelte";
+import ToastWrapper from "@components/toasts/ToastWrapper.svelte";
+import Layout from "@layouts/Layout.astro";
+import SettingsLayout from "@layouts/SettingsLayout.astro";
+import SettingsSection from "@layouts/SettingsSection.astro";
+import { getLangFromUrl, useTranslations } from "../../../i18n/utils";
+const lang = getLangFromUrl(Astro.url);
+const t = useTranslations(lang);
+export function getStaticPaths() {
+ const STATIC_PATHS = [{ params: { lang: "en_US" } }, { params: { lang: "jp" } }];
+ return STATIC_PATHS;
+}
+export const prerender = true;
+---
+
+
+
+
+
+
+
+
+
+
+ { /* The toast notifications :D */ }
+
+
+
+
+
+
+
diff --git a/src/pages/_404.tsx b/src/pages/_404.tsx
deleted file mode 100644
index 07c036da..00000000
--- a/src/pages/_404.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { useTranslation } from "react-i18next";
-import { Link } from "preact-router";
-import { HeaderRoute } from "../components/HeaderRoute";
-import CloakedHead from "../util/CloakedHead";
-
-export function NotFound() {
- const { t } = useTranslation();
-
- return (
-
-
-
-
-
-
-
- {t("404.text")}
-
-
404
-
-
-
- {t("404.return")}
-
-
-
-
-
- );
-}
diff --git a/src/pages/config.json b/src/pages/config.json
deleted file mode 100644
index 4d20b553..00000000
--- a/src/pages/config.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "prod": false
-}
diff --git a/src/pages/discord.tsx b/src/pages/discord.tsx
deleted file mode 100644
index 99c356ff..00000000
--- a/src/pages/discord.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import { useTranslation } from "react-i18next";
-import { HeaderRoute } from "../components/HeaderRoute";
-import CloakedHead from "../util/CloakedHead";
-
-export function DiscordPage() {
- const { t } = useTranslation();
-
- return (
-
-
-
-
- );
-}
diff --git a/src/pages/index.astro b/src/pages/index.astro
new file mode 100644
index 00000000..24c50b5a
--- /dev/null
+++ b/src/pages/index.astro
@@ -0,0 +1,48 @@
+---
+import Loading from "@components/Loading.astro";
+import Layout from "@layouts/Layout.astro";
+---
+
+
+
+
+
+
+ JavaScript is required to run this app.
+
diff --git a/src/pages/loading.astro b/src/pages/loading.astro
new file mode 100644
index 00000000..042197b6
--- /dev/null
+++ b/src/pages/loading.astro
@@ -0,0 +1,27 @@
+---
+import LoadingComponent from "@components/Loading.astro";
+import Layout from "@layouts/Layout.astro";
+---
+
+
+
+
+
diff --git a/src/routes.tsx b/src/routes.tsx
deleted file mode 100644
index e0aaf8fa..00000000
--- a/src/routes.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import { LocationProvider, Router, Route } from "preact-iso";
-import { Home } from "./pages/Home";
-import { NotFound } from "./pages/_404";
-import { DiscordPage } from "./pages/discord";
-import { ProxyFrame } from "./pages/ProxyFrame.js";
-import { Radon } from "./pages/Radon";
-import { Settings } from "./pages/Settings/";
-import { AboutBlank } from "./AboutBlank";
-import { Faq } from "./pages/Faq";
-// import { registerRemoteListener } from "@mercuryworkshop/bare-mux";
-import "./style.css";
-import "./i18n";
-
-export default function Routes() {
- const wispUrl =
- (location.protocol === "https:" ? "wss://" : "ws://") +
- location.host +
- "/wisp/"; // @TODO Japan - US ping
- if ("serviceWorker" in navigator) {
- navigator.serviceWorker.ready.then(async () => {
- //await registerRemoteListener(sw.active!)
- console.log("SW ready")
- });
- navigator.serviceWorker.register("/sw.js", {
- scope: "/"
- });
- }
- return (
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/src/store.js b/src/store.js
new file mode 100644
index 00000000..c704662f
--- /dev/null
+++ b/src/store.js
@@ -0,0 +1,3 @@
+import { atom } from "nanostores";
+
+export const isMobileNavOpen = atom(false);
diff --git a/src/style.css b/src/style.css
deleted file mode 100644
index 71a7c5c1..00000000
--- a/src/style.css
+++ /dev/null
@@ -1,138 +0,0 @@
-@import url("https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;700;900&display=swap");
-@import url("https://fonts.googleapis.com/css2?family=Dongle&family=Roboto:wght@100&display=swap");
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
-@layer base {
- :root,
- .main {
- --background-primary: #191724;
- --background-lighter: #16121f;
- --navbar-color: #26233a;
- --navbar-height: 60px;
- --navbar-text-color: #7967dd;
- --navbar-link-color: #e0def4;
- --navbar-link-hover-color: gray;
- --navbar-font: "Roboto";
- --input-text-color: #e0def4;
- --input-placeholder-color: white;
- --input-background-color: #1f1d2e;
- --input-border-color: #eb6f92;
- --input-border-size: 1.3px;
- --navbar-logo-filter: none;
- --dropdown-option-hover-color: #312a49;
- --tab-color: var(--black);
- --border-color: #16121f;
- }
- .hacker {
- --background-primary: #000 !important;
- --background-lighter: #000 !important;
- --navbar-color: #000 !important;
- --navbar-height: 60px !important;
- --navbar-text-color: greenyellow !important;
- --navbar-link-color: greenyellow !important;
- --navbar-link-hover-color: green !important;
- --navbar-font: "Roboto" !important;
- --input-text-color: greenyellow !important;
- --input-placeholder-color: white !important;
- --input-background-color: #000 !important;
- --input-border-color: greenyellow !important;
- --input-border-size: 1.3px !important;
- --navbar-logo-filter: none !important;
- --dropdown-option-hover-color: #312a49 !important;
- --tab-color: var(--black) !important;
- --border-color: greenyellow !important;
- }
- .catppuccin-mocha {
- --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;
- }
- .catppuccin-macchiato {
- --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;
- }
- .catppuccin-frappe {
- --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;
- }
- .catppuccin-latte {
- --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;
- }
-}
-body {
- @apply bg-primary;
- background-image: var(--background-image);
- background-position: center;
- background-size: cover;
- background-attachment: fixed;
-}
-
-.font-inter {
- font-family: "Inter", sans-serif;
- font-weight: 300;
-}
-
-.font-roboto {
- font-family: "Roboto";
-}
diff --git a/src/util/CloakedHead.tsx b/src/util/CloakedHead.tsx
deleted file mode 100644
index 48b460fb..00000000
--- a/src/util/CloakedHead.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import { Helmet } from "react-helmet";
-
-interface Props {
- originalTitle: string;
- originalFavicon: string;
-}
-
-const CloakedHead = (props: Props) => {
- var isTitleCloaked =
- localStorage.getItem("cloakTitle") !== null
- ? localStorage.getItem("cloakTitle") !== "none"
- : false;
-
- var isFaviconCloaked =
- localStorage.getItem("cloakFavicon") !== null
- ? localStorage.getItem("cloakFavicon") !== "none"
- : false;
-
- return (
-
-
- {isTitleCloaked
- ? localStorage.getItem("cloakTitle")
- : props.originalTitle}
-
-
-
- );
-};
-
-export default CloakedHead;
diff --git a/src/util/IDB.js b/src/util/IDB.js
deleted file mode 100644
index 8b28921e..00000000
--- a/src/util/IDB.js
+++ /dev/null
@@ -1,22 +0,0 @@
-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 };
diff --git a/src/util/IosDetector.tsx b/src/util/IosDetector.tsx
deleted file mode 100644
index d2c3a0ce..00000000
--- a/src/util/IosDetector.tsx
+++ /dev/null
@@ -1,7 +0,0 @@
-export function isIOS() {
- if (/iPad|iPhone|iPod/.test(navigator.userAgent)) {
- return true;
- } else {
- return false;
- }
-}
diff --git a/src/util/RammerheadEncode.ts b/src/util/RammerheadEncode.ts
deleted file mode 100644
index b3808d34..00000000
--- a/src/util/RammerheadEncode.ts
+++ /dev/null
@@ -1,177 +0,0 @@
-export function RammerheadEncode(baseUrl) {
- // Hellhead
- const mod = (n, m) => ((n % m) + m) % m;
- const baseDictionary =
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~-";
- const shuffledIndicator = "_rhs";
- const generateDictionary = function () {
- let str = "";
- const split = baseDictionary.split("");
- while (split.length > 0) {
- str += split.splice(Math.floor(Math.random() * split.length), 1)[0];
- }
- return str;
- };
- interface StrShuffler {
- dictionary: any;
- }
- class StrShuffler {
- constructor(dictionary = generateDictionary()) {
- this.dictionary = dictionary;
- }
- shuffle(str) {
- if (str.startsWith(shuffledIndicator)) {
- return str;
- }
- let shuffledStr = "";
- for (let i = 0; i < str.length; i++) {
- const char = str.charAt(i);
- const idx = baseDictionary.indexOf(char);
- if (char === "%" && str.length - i >= 3) {
- shuffledStr += char;
- shuffledStr += str.charAt(++i);
- shuffledStr += str.charAt(++i);
- } else if (idx === -1) {
- shuffledStr += char;
- } else {
- shuffledStr += this.dictionary.charAt(
- mod(idx + i, baseDictionary.length)
- );
- }
- }
- return shuffledIndicator + shuffledStr;
- }
- unshuffle(str) {
- if (!str.startsWith(shuffledIndicator)) {
- return str;
- }
-
- str = str.slice(shuffledIndicator.length);
-
- let unshuffledStr = "";
- for (let i = 0; i < str.length; i++) {
- const char = str.charAt(i);
- const idx = this.dictionary.indexOf(char);
- if (char === "%" && str.length - i >= 3) {
- unshuffledStr += char;
- unshuffledStr += str.charAt(++i);
- unshuffledStr += str.charAt(++i);
- } else if (idx === -1) {
- unshuffledStr += char;
- } else {
- unshuffledStr += baseDictionary.charAt(
- mod(idx - i, baseDictionary.length)
- );
- }
- }
- return unshuffledStr;
- }
- }
- function get(url, callback, shush = false) {
- var request = new XMLHttpRequest();
- request.open("GET", url, true);
- request.send();
-
- request.onerror = function () {
- if (!shush) console.log("Cannot communicate with the server");
- };
- request.onload = function () {
- if (request.status === 200) {
- callback(request.responseText);
- } else {
- if (!shush)
- console.log(
- 'unexpected server response to not match "200". Server says "' +
- request.responseText +
- '"'
- );
- }
- };
- }
- var api = {
- newsession(callback) {
- get("/newsession", callback);
- },
- sessionexists(id, callback) {
- get("/sessionexists?id=" + encodeURIComponent(id), function (res) {
- if (res === "exists") return callback(true);
- if (res === "not found") return callback(false);
- console.log("unexpected response from server. received" + res);
- });
- },
- shuffleDict(id, callback) {
- console.log("Shuffling", id);
- get("/api/shuffleDict?id=" + encodeURIComponent(id), function (res) {
- callback(JSON.parse(res));
- });
- }
- };
- var localStorageKey = "rammerhead_sessionids";
- var localStorageKeyDefault = "rammerhead_default_sessionid";
- var sessionIdsStore = {
- get() {
- var rawData = localStorage.getItem(localStorageKey);
- if (!rawData) return [];
- try {
- var data = JSON.parse(rawData);
- if (!Array.isArray(data)) throw "getout";
- return data;
- } catch (e) {
- return [];
- }
- },
- set(data) {
- if (!data || !Array.isArray(data)) throw new TypeError("must be array");
- localStorage.setItem(localStorageKey, JSON.stringify(data));
- },
- getDefault() {
- var sessionId = localStorage.getItem(localStorageKeyDefault);
- if (sessionId) {
- var data = sessionIdsStore.get();
- data.filter(function (e) {
- return e.id === sessionId;
- });
- if (data.length) return data[0];
- }
- return null;
- },
- setDefault(id) {
- localStorage.setItem(localStorageKeyDefault, id);
- }
- };
- function addSession(id) {
- var data = sessionIdsStore.get();
- data.unshift({ id: id, createdOn: new Date().toLocaleString() });
- sessionIdsStore.set(data);
- }
- function getSessionId() {
- return new Promise((resolve) => {
- var id = localStorage.getItem("session-string");
- api.sessionexists(id, function (value) {
- if (!value) {
- console.log("Session validation failed");
- api.newsession(function (id) {
- addSession(id);
- localStorage.setItem("session-string", id);
- console.log(id);
- console.log("^ new id");
- resolve(id);
- });
- } else {
- resolve(id);
- }
- });
- });
- }
- var ProxyHref;
-
- return getSessionId().then((id) => {
- return new Promise((resolve, reject) => {
- api.shuffleDict(id, function (shuffleDict) {
- var shuffler = new StrShuffler(shuffleDict);
- ProxyHref = "/" + id + "/" + shuffler.shuffle(baseUrl);
- resolve(ProxyHref);
- });
- });
- });
-}
diff --git a/src/util/SWHelper.js b/src/util/SWHelper.js
deleted file mode 100644
index 87220088..00000000
--- a/src/util/SWHelper.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import { setTransport } from "./transports.ts";
-
-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");
- }
- });
-}
-
-function registerServiceWorker() {
- if ("serviceWorker" in navigator) {
- navigator.serviceWorker
- .register("/sw.js", {
- scope: "/~/"
- })
- .then(() => {
- console.log("Service worker registered successfully");
- setTransport();
- });
- }
-}
-
-export { updateServiceWorkers, uninstallServiceWorkers, registerServiceWorker };
diff --git a/src/util/SiteSupport.json b/src/util/SiteSupport.json
deleted file mode 100644
index d7814a47..00000000
--- a/src/util/SiteSupport.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "discord.gg": "ultraviolet",
- "discord.com": "ultraviolet",
- "example.org": "rammerhead",
- "example.com": "ultraviolet",
- "spotify.com": "dynamic",
- "spotify.link": "dynamic",
- "youtube.com": "ultraviolet",
- "youtu.be": "ultraviolet"
-}
diff --git a/src/util/searchUtil.ts b/src/util/searchUtil.ts
deleted file mode 100644
index 4d56a269..00000000
--- a/src/util/searchUtil.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-export function searchUtil(input: string, template: string) {
- try {
- return new URL(input).toString();
- } catch (error) {}
- try {
- const url = new URL(`http://${input}`);
- if (url.hostname.includes(".")) return url.toString();
- } catch (error) {}
- return template.replace("%s", encodeURIComponent(input));
-}
diff --git a/src/util/transports.ts b/src/util/transports.ts
deleted file mode 100644
index 09ec0f86..00000000
--- a/src/util/transports.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-import {
- SetTransport,
- registerRemoteListener
-} from "@mercuryworkshop/bare-mux";
-//import { isIOS } from "./IosDetector";
-
-declare global {
- interface Window {
- setTransport: () => void;
- }
-}
-
-function changeTransport(transport: string, wispUrl: string) {
- switch (transport) {
- case "epoxy":
- localStorage.setItem("transport", "epoxy");
- console.log("Setting transport to Epoxy");
- SetTransport("EpxMod.EpoxyClient", { wisp: wispUrl });
- break;
- case "libcurl":
- localStorage.setItem("transport", "libcurl");
- console.log("Setting transport to Libcurl");
- SetTransport("CurlMod.LibcurlClient", {
- wisp: wispUrl
- });
- break;
- case "bare":
- localStorage.setItem("transport", "bare");
- console.log("Setting transport to Bare");
- const bare =
- localStorage.getItem("bare") || window.location.origin + "/bare/";
- console.log("Bare URL: " + bare);
- SetTransport("BareMod.BareClient", bare);
- break;
- default:
- SetTransport("CurlMod.LibcurlClient", {
- wisp: wispUrl
- });
- break;
- }
-}
-
-function getTransport() {
- return localStorage.getItem("transport") || "epoxy";
-}
-
-const wispUrl =
- (location.protocol === "https:" ? "wss://" : "ws://") +
- location.host +
- "/wisp/";
-//registerRemoteListener(navigator.serviceWorker.controller!);
-
-//if (isIOS) {
-// console.log("iOS device detected. Bare will be used.");
-// changeTransport(
-// localStorage.getItem("transport") || "libcurl",
-// localStorage.getItem("wispUrl") || wispUrl
-// );
-//} else {
-// changeTransport(
-// localStorage.getItem("transport") || "bare",
-// localStorage.getItem("wispUrl") || wispUrl
-// );
-//}
-
-//changeTransport(
-// localStorage.getItem("transport") || "libcurl",
-// localStorage.getItem("wispUrl") || wispUrl
-//);
-
-// helper function for ../routes.tsx
-function setTransport() {
- changeTransport(
- localStorage.getItem("transport") || "epoxy",
- localStorage.getItem("wispUrl") || wispUrl
- );
-}
-
-window.setTransport = setTransport;
-
-export { changeTransport, getTransport, setTransport };
diff --git a/src/utils/events.ts b/src/utils/events.ts
new file mode 100644
index 00000000..16f8a015
--- /dev/null
+++ b/src/utils/events.ts
@@ -0,0 +1,13 @@
+function pageLoad(fn: () => void, logging?: boolean) {
+ document.addEventListener("astro:page-load", () => {
+ try {
+ fn();
+ } catch (err) {
+ if (logging) {
+ console.error(err);
+ }
+ }
+ });
+}
+
+export { pageLoad };
diff --git a/src/utils/libcurl.ts b/src/utils/libcurl.ts
new file mode 100644
index 00000000..58c3fe1e
--- /dev/null
+++ b/src/utils/libcurl.ts
@@ -0,0 +1,28 @@
+import { WispServerURLS } from "@utils/settings/index";
+//helper for libcurl as we have to use it in multiple locations and we don't want to re-download the WASM every time
+//@ts-expect-error No types, expected. See: https://github.com/ading2210/libcurl.js for docs on how to use.
+import { libcurl } from "libcurl.js-new/bundled";
+let clientExists: boolean = false;
+async function initLibcurl() {
+ if (!clientExists) {
+ await libcurl.load_wasm();
+ libcurl.set_websocket(WispServerURLS.default);
+ console.debug("Libcurl ready?", libcurl.ready);
+ clientExists = true;
+ }
+}
+
+type fetchType = "json" | "text";
+
+async function fetchFromLibcurl(url: string, type: fetchType): Promise
{
+ const res = await libcurl.fetch(url);
+ const data = type === "json" ? await res.json() : await res.text();
+ return data;
+}
+
+const client = {
+ initLibcurl,
+ fetchFromLibcurl
+};
+
+export { client };
diff --git a/src/utils/registerSW.ts b/src/utils/registerSW.ts
new file mode 100644
index 00000000..e09e427b
--- /dev/null
+++ b/src/utils/registerSW.ts
@@ -0,0 +1,60 @@
+import { BareMuxConnection } from "@mercuryworkshop/bare-mux";
+import { Settings, WispServerURLS } from "./settings/index";
+function loadProxyScripts() {
+ //wrap everything in a promise to avoid race conditions
+ return new Promise((resolve) => {
+ const conn = new BareMuxConnection("/baremux/worker.js");
+ if (typeof __uv$config !== "undefined") {
+ return resolve(conn);
+ }
+ const uvBundle = document.createElement("script");
+ uvBundle.src = "/uv/uv.bundle.js";
+ uvBundle.defer = true;
+ document.body.appendChild(uvBundle);
+ const uvConfig = document.createElement("script");
+ uvConfig.src = "/uv/uv.config.js";
+ uvConfig.defer = true;
+ document.body.appendChild(uvConfig);
+ const checkScript = setInterval(() => {
+ if (typeof __uv$config !== "undefined") {
+ clearInterval(checkScript);
+ resolve(conn);
+ }
+ }, 100);
+ });
+}
+
+function setTransport(conn: BareMuxConnection, transport?: string) {
+ //wrap in a promise so we don't register sw until a transport is set.
+ const wispServer = localStorage.getItem(Settings.ProxySettings.wispServerURL);
+ return new Promise((resolve) => {
+ switch (transport) {
+ case "epoxy":
+ conn.setTransport("/epoxy/index.mjs", [
+ { wisp: wispServer ? WispServerURLS[wispServer] : WispServerURLS.default }
+ ]);
+ break;
+ case "libcurl":
+ conn.setTransport("/libcurl/index.mjs", [
+ { wisp: wispServer ? WispServerURLS[wispServer] : WispServerURLS.default }
+ ]);
+ break;
+ }
+ resolve();
+ });
+}
+
+function initSw() {
+ //this is wrapped in a promise to mostly solve the bare-mux v1 problems
+ return new Promise((resolve) => {
+ if ("serviceWorker" in navigator) {
+ navigator.serviceWorker.ready.then(async (reg) => {
+ console.debug("Service worker ready!");
+ resolve(reg);
+ });
+ navigator.serviceWorker.register("/sw.js", { scope: "/" });
+ }
+ });
+}
+
+export { initSw, setTransport, loadProxyScripts };
diff --git a/src/utils/search.ts b/src/utils/search.ts
new file mode 100644
index 00000000..cb810959
--- /dev/null
+++ b/src/utils/search.ts
@@ -0,0 +1,27 @@
+function search(input: string, template: string) {
+ try {
+ // input is a valid URL:
+ // eg: https://example.com, https://example.com/test?q=param
+ return new URL(input).toString();
+ } catch (err) {
+ // input was not a valid URL
+ }
+
+ try {
+ // input is a valid URL when http:// is added to the start:
+ // eg: example.com, https://example.com/test?q=param
+ const url = new URL(`http://${input}`);
+ // only if the hostname has a TLD/subdomain
+ if (url.hostname.includes(".")) return url.toString();
+ } catch (err) {
+ // input was not valid URL
+ }
+
+ // input may have been a valid URL, however the hostname was invalid
+
+ // Attempts to convert the input to a fully qualified URL have failed
+ // Treat the input as a search query
+ return template.replace("%s", encodeURIComponent(input));
+}
+
+export { search };
diff --git a/src/utils/settings/index.ts b/src/utils/settings/index.ts
new file mode 100644
index 00000000..946dfd33
--- /dev/null
+++ b/src/utils/settings/index.ts
@@ -0,0 +1,54 @@
+//Combine all of the other settings into one object. And export that (along with types and other things)
+import {
+ AppearanceSettings,
+ MarketPlaceExtras,
+ PluginSettings,
+ marketPlaceSettings
+} from "./marketplace";
+import { ProxySettings, proxySettings } from "./proxy";
+import { TabSettings, cloak, tabSettings } from "./tab";
+import {
+ type AbCloaks,
+ type OpenIn,
+ type Package,
+ type PackageType,
+ type Proxy,
+ type SearchEngine,
+ SearchEngines,
+ type TabCloaks,
+ type Transport,
+ WispServerURLS,
+ wispUrl
+} from "./types";
+
+const Settings = {
+ AppearanceSettings,
+ TabSettings,
+ ProxySettings,
+ MarketPlaceExtras,
+ PluginSettings
+};
+
+const settings = {
+ marketPlaceSettings,
+ tabSettings,
+ proxySettings
+};
+
+//export all of the stuffs
+export {
+ Settings,
+ settings,
+ SearchEngines,
+ WispServerURLS,
+ wispUrl,
+ cloak,
+ type TabCloaks,
+ type AbCloaks,
+ type OpenIn,
+ type Proxy,
+ type Transport,
+ type PackageType,
+ type Package,
+ type SearchEngine
+};
diff --git a/src/utils/settings/marketplace.ts b/src/utils/settings/marketplace.ts
new file mode 100644
index 00000000..2cd59fe9
--- /dev/null
+++ b/src/utils/settings/marketplace.ts
@@ -0,0 +1,225 @@
+//marketplace code & handlers
+import { Settings } from ".";
+import {
+ type Package,
+ type PackageType,
+ type Plugin,
+ type PluginType,
+ type SWPagePlugin,
+ type SWPlugin
+} from "./types";
+const AppearanceSettings = {
+ themes: "nebula||themes",
+ themeName: "nebula||themeName",
+ stylePayload: "nebula||stylepayload",
+ video: "nebula||video",
+ image: "nebula||image"
+};
+
+const PluginSettings = {
+ plugins: "nebula||plugins"
+};
+
+const MarketPlaceExtras = {
+ proxy: "nebula||marketplaceProxy",
+ hostname: "nebula||marketplaceHostname"
+};
+
+const marketPlaceSettings = {
+ install: function (p: Package, packageName: string, payload?: any) {
+ return new Promise((resolve) => {
+ if (p.theme) {
+ let themes = localStorage.getItem(AppearanceSettings.themes) as any;
+ themes ? (themes = JSON.parse(themes)) : (themes = []);
+ if (!themes.find((theme: any) => theme === packageName)) {
+ themes.push(packageName);
+ localStorage.setItem(AppearanceSettings.themes, JSON.stringify(themes));
+ this.changeTheme(false, payload, p.theme.video, p.theme.bgImage, packageName);
+ }
+ resolve();
+ }
+ if (p.plugin) {
+ let plugins = localStorage.getItem(PluginSettings.plugins) as any;
+ plugins ? (plugins = JSON.parse(plugins)) : (plugins = []);
+ //@ts-ignore
+ const plugin = plugins.find(({ name }) => name === packageName) as Plugin;
+ if (!plugin) {
+ plugins.push({
+ name: packageName,
+ src: p.plugin.src,
+ type: p.plugin.type
+ } as unknown as Plugin);
+ localStorage.setItem(PluginSettings.plugins, JSON.stringify(plugins));
+ } else if (plugin && plugin.remove) {
+ plugin.remove = false;
+ localStorage.setItem(Settings.PluginSettings.plugins, JSON.stringify(plugins));
+ }
+ resolve();
+ }
+ });
+ },
+ uninstall: function (p: PackageType, packageName: string) {
+ console.log(p);
+ return new Promise((resolve) => {
+ if (p === "theme") {
+ let items = localStorage.getItem(AppearanceSettings.themes) as any;
+ items ? (items = JSON.parse(items)) : (items = []);
+ if (items.find((theme: any) => theme === packageName.toLowerCase())) {
+ const idx = items.indexOf(packageName.toLowerCase());
+ items.splice(idx, 1);
+ localStorage.setItem(AppearanceSettings.themes, JSON.stringify(items));
+ this.changeTheme(true);
+ }
+ resolve();
+ }
+ if (p === "plugin-page" || p === "plugin-sw") {
+ let plugins = localStorage.getItem(PluginSettings.plugins) as any;
+ plugins ? (plugins = JSON.parse(plugins)) : (plugins = []);
+ //@ts-ignore
+ const plugin = plugins.find(({ name }) => name === packageName.toLowerCase());
+ if (plugin) {
+ plugin.remove = true;
+ localStorage.setItem(PluginSettings.plugins, JSON.stringify(plugins));
+ }
+ resolve();
+ }
+ });
+ },
+ handlePlugins: function (worker: never | ServiceWorkerRegistration) {
+ return new Promise((resolve) => {
+ let plugins =
+ JSON.parse(localStorage.getItem(Settings.PluginSettings.plugins) as string) || [];
+ const swPagePlugins: SWPagePlugin[] = [];
+ const swPlugins: SWPlugin[] = [];
+ if (plugins.length === 0) {
+ console.log("Plugin length is not greater then 0. Resolving.");
+ return resolve();
+ }
+ plugins.forEach(async (plugin: Plugin) => {
+ if (plugin.type === "page") {
+ const pluginScript = await fetch(
+ `/packages/${plugin.name.toLowerCase()}/${plugin.src}`
+ ).then((res) => res.text());
+ const script = eval(pluginScript);
+ const inject = (await script()) as unknown as SWPagePlugin;
+ if (plugin.remove) {
+ plugins = plugins.filter(
+ //@ts-ignore freaking types BRO
+ ({ name }) => name !== plugin.name.toLowerCase()
+ );
+ swPagePlugins.push({
+ remove: true,
+ host: inject.host,
+ html: inject.html,
+ injectTo: inject.injectTo,
+ type: "page"
+ });
+ } else {
+ swPagePlugins.push({
+ host: inject.host,
+ html: inject.html,
+ injectTo: inject.injectTo,
+ type: "page"
+ });
+ }
+ //only resolve AFTER we have postMessaged to the SW.
+ worker.active?.postMessage(swPagePlugins);
+ } else if (plugin.type === "serviceWorker") {
+ const pluginScript = await fetch(
+ `/packages/${plugin.name.toLowerCase()}/${plugin.src}`
+ ).then((res) => res.text());
+ const script = eval(pluginScript);
+ const inject = (await script()) as unknown as SWPlugin;
+ if (plugin.remove) {
+ plugins = plugins.filter(
+ //@ts-ignore
+ ({ name }) => name !== plugin.name.toLowerCase()
+ );
+ swPlugins.push({
+ remove: true,
+ function: inject.function.toString(),
+ name: plugin.name,
+ events: inject.events,
+ type: "serviceWorker"
+ });
+ } else {
+ swPlugins.push({
+ function: inject.function.toString(),
+ name: plugin.name,
+ events: inject.events,
+ type: "serviceWorker"
+ });
+ }
+ worker.active?.postMessage(swPlugins);
+ }
+ localStorage.setItem(Settings.PluginSettings.plugins, JSON.stringify(plugins));
+ resolve();
+ });
+ });
+ },
+ changeTheme: async function (
+ reset: Boolean,
+ payload?: any,
+ videoSource?: string,
+ bgSource?: string,
+ name?: string
+ ) {
+ async function resetCSS() {
+ const stylesheet = document.getElementById("stylesheet")! as HTMLLinkElement;
+ localStorage.removeItem(AppearanceSettings.stylePayload);
+ localStorage.removeItem(AppearanceSettings.themeName);
+ stylesheet.href = "/nebula.css";
+ }
+ function resetVideo() {
+ localStorage.removeItem(AppearanceSettings.video);
+ const source = document.getElementById("nebulaVideo")! as HTMLVideoElement;
+ source.src = "";
+ }
+ function resetBGImage() {
+ localStorage.removeItem(AppearanceSettings.image);
+ const image = document.getElementById("nebulaImage")! as HTMLImageElement;
+ image.style.display = "none";
+ image.src = "";
+ }
+ if (reset === true) {
+ await resetCSS();
+ await resetCSS();
+ resetBGImage();
+ resetVideo();
+ }
+ if (videoSource || localStorage.getItem(AppearanceSettings.video)) {
+ resetBGImage();
+ resetVideo();
+ const source = document.getElementById("nebulaVideo")! as HTMLVideoElement;
+ if (!localStorage.getItem(AppearanceSettings.video)) {
+ localStorage.setItem(AppearanceSettings.video, videoSource as string);
+ }
+ source.src = `/packages/${name}/${videoSource ? videoSource : localStorage.getItem(AppearanceSettings.video)}`;
+ }
+ if (bgSource || localStorage.getItem(AppearanceSettings.image)) {
+ resetVideo();
+ resetBGImage();
+ const image = document.getElementById("nebulaImage")! as HTMLImageElement;
+ if (!localStorage.getItem(AppearanceSettings.image)) {
+ localStorage.setItem(AppearanceSettings.image, bgSource as string);
+ }
+ image.style.display = "block";
+ image.src = `/packages/${name}/${bgSource ? bgSource : localStorage.getItem(AppearanceSettings.image)}`;
+ }
+ if (payload) {
+ const stylesheet = document.getElementById("stylesheet")! as HTMLLinkElement;
+ if (localStorage.getItem(AppearanceSettings.stylePayload) !== payload) {
+ localStorage.setItem(AppearanceSettings.stylePayload, payload);
+ localStorage.setItem(AppearanceSettings.themeName, name as string);
+ }
+ stylesheet.href = `/packages/${name}/${localStorage.getItem(AppearanceSettings.stylePayload)}`;
+ } else {
+ if (localStorage.getItem(AppearanceSettings.stylePayload)) {
+ const stylesheet = document.getElementById("stylesheet")! as HTMLLinkElement;
+ stylesheet.href = `/packages/${localStorage.getItem(AppearanceSettings.themeName)}/${localStorage.getItem(AppearanceSettings.stylePayload)}`;
+ }
+ }
+ }
+};
+
+export { AppearanceSettings, PluginSettings, MarketPlaceExtras, marketPlaceSettings };
diff --git a/src/utils/settings/proxy.ts b/src/utils/settings/proxy.ts
new file mode 100644
index 00000000..d5df9439
--- /dev/null
+++ b/src/utils/settings/proxy.ts
@@ -0,0 +1,29 @@
+//Proxy specific settings.
+import { type OpenIn, type Proxy, type SearchEngine, type Transport } from "./types";
+const ProxySettings = {
+ proxy: "nebula||proxy",
+ openIn: "nebula||open",
+ searchEngine: "nebula||searchEngine",
+ wispServerURL: "nebula||wisp",
+ transport: "nebula||transport"
+};
+
+const proxySettings = {
+ changeProxy: function (proxy: Proxy | string) {
+ localStorage.setItem(ProxySettings.proxy, proxy);
+ },
+ openIn: function (type: OpenIn | string) {
+ localStorage.setItem(ProxySettings.openIn, type);
+ },
+ setSearchEngine: function (searchEngine: SearchEngine | string) {
+ localStorage.setItem(ProxySettings.searchEngine, searchEngine);
+ },
+ setWispURL: function (server: string) {
+ localStorage.setItem(ProxySettings.wispServerURL, server);
+ },
+ setTransport: function (transport: Transport | string) {
+ localStorage.setItem(ProxySettings.transport, transport);
+ }
+};
+
+export { ProxySettings, proxySettings };
diff --git a/src/utils/settings/tab.ts b/src/utils/settings/tab.ts
new file mode 100644
index 00000000..fd3abcea
--- /dev/null
+++ b/src/utils/settings/tab.ts
@@ -0,0 +1,83 @@
+//Tab specific settings.
+import { type AbCloaks, type TabCloaks } from "./types";
+const TabSettings = {
+ tabCloak: "nebula||tabCloak",
+ abblob: "nebula||abBlob"
+};
+
+function cloak(cloak: AbCloaks | string, redirect: string, url: string) {
+ switch (cloak) {
+ case "a:b":
+ window.location.replace(redirect);
+ const win = window.open();
+ win!.document.body.style.margin = "0";
+ win!.document.body.style.height = "100vh";
+ const iframe = win!.document.createElement("iframe");
+ iframe.style.border = "none";
+ iframe.style.width = "100%";
+ iframe.style.height = "100%";
+ iframe.style.margin = "0";
+ iframe.src = url;
+ win!.document.body.appendChild(iframe);
+ break;
+ case "blob":
+ const htmlContent = `
+
+
+
+
+
+
+
+
+
+ `;
+ window.location.replace("https://google.com");
+ const blob = new Blob([htmlContent], { type: "text/html" });
+ const blobURL = URL.createObjectURL(blob);
+ window.open(blobURL, "_blank");
+ break;
+ }
+}
+
+const tabSettings = {
+ cloakTab: function (cloak: TabCloaks | string) {
+ const faviconElement = document.getElementById("favicon") as HTMLLinkElement;
+ localStorage.setItem(TabSettings.tabCloak, cloak);
+ switch (cloak) {
+ case "google":
+ document.title = "Google";
+ faviconElement.href = "/cloaks/google.png";
+ break;
+ case "wikipedia":
+ document.title = "Wikipedia";
+ faviconElement.href = "/cloaks/wikipedia.ico";
+ break;
+ case "canvas":
+ document.title = "Dashboard";
+ faviconElement.href = "/cloaks/canvas.ico";
+ break;
+ case "classroom":
+ document.title = "Home";
+ faviconElement.href = "/cloaks/classroom.png";
+ break;
+ case "powerschool":
+ document.title = "PowerSchool";
+ faviconElement.href = "/cloaks/ps.ico";
+ break;
+ case "reset":
+ //force a reset of favicon & title
+ localStorage.setItem("nebula||tabCloak", "default");
+ window.location.reload();
+ default:
+ return;
+ }
+ },
+ abCloak: function (type: AbCloaks | string) {
+ localStorage.setItem(TabSettings.abblob, type);
+ cloak(type as AbCloaks, "https://google.com", window.location.href);
+ }
+};
+export { tabSettings, TabSettings, cloak };
diff --git a/src/utils/settings/types.ts b/src/utils/settings/types.ts
new file mode 100644
index 00000000..7c6648a1
--- /dev/null
+++ b/src/utils/settings/types.ts
@@ -0,0 +1,65 @@
+const wispUrl = (location.protocol === "https:" ? "wss://" : "ws://") + location.host + "/wisp/";
+type TabCloaks = "default" | "google" | "wikipedia" | "canvas" | "classroom" | "powerschool";
+type AbCloaks = "a:b" | "blob";
+type OpenIn = "a:b" | "blob" | "direct" | "embed";
+type Proxy = "automatic" | "uv" | "rh";
+type Transport = "epoxy" | "libcurl";
+const SearchEngines: Record = {
+ ddg: "https://duckduckgo.com/?q=%s",
+ google: "https://google.com/search?q=%s",
+ bing: "https://bing.com/search?q=%s"
+};
+type SearchEngine = "ddg" | "google" | "bing";
+const WispServerURLS: Record = {
+ default: wispUrl,
+ ruby: "wss://ruby.rubynetwork.co/wisp/"
+};
+
+
+type PluginType = "page" | "serviceWorker";
+type MarketplacePluginType = "plugin-page" | "plugin-sw";
+type PackageType = "theme" | MarketplacePluginType;
+
+interface Plugin {
+ name: string;
+ src: string;
+ type: PluginType;
+ remove?: boolean;
+}
+interface SWPagePlugin extends Omit {
+ host: string;
+ html: string;
+ injectTo: "head" | "body";
+}
+
+interface SWPlugin extends Omit {
+ function: any;
+ events: [];
+}
+
+interface Package {
+ theme?: {
+ payload: string;
+ video?: string;
+ bgImage?: string;
+ };
+ plugin?: Plugin;
+}
+
+export {
+ type TabCloaks,
+ type AbCloaks,
+ type OpenIn,
+ type Proxy,
+ type Transport,
+ type PackageType,
+ type Package,
+ type PluginType,
+ type Plugin,
+ type SWPagePlugin,
+ type SWPlugin,
+ SearchEngines,
+ type SearchEngine,
+ WispServerURLS,
+ wispUrl
+};
diff --git a/src/utils/siteSupport.ts b/src/utils/siteSupport.ts
new file mode 100644
index 00000000..dec922df
--- /dev/null
+++ b/src/utils/siteSupport.ts
@@ -0,0 +1,13 @@
+import type { Proxy } from "./settings";
+type ProxyChoices = Exclude;
+
+const SupportedSites: Record = {
+ "discord.gg": "uv",
+ "discord.com": "uv",
+ "spotify.com": "rh",
+ "spotify.link": "rh",
+ "youtube.com": "uv",
+ "youtu.be": "uv"
+};
+
+export { SupportedSites };
diff --git a/src/utils/toast.ts b/src/utils/toast.ts
new file mode 100644
index 00000000..81933323
--- /dev/null
+++ b/src/utils/toast.ts
@@ -0,0 +1,28 @@
+type ToastType = "success" | "error" | "multiline";
+type Position =
+ | "top-left"
+ | "top-middle"
+ | "top-right"
+ | "bottom-left"
+ | "bottom-right"
+ | "bottom-center";
+interface Props {
+ toastType: ToastType;
+ text: string;
+ class: string;
+ id?: string;
+ duration?: number;
+ emoji?: any;
+ position?: Position;
+}
+
+function toast(query: string) {
+ const wrapper = document.getElementById("toastwrapper") as HTMLDivElement;
+ wrapper.classList.remove("hidden");
+ //this is a really hacky solution for toast notifications LOL
+ const element = document.querySelector(query) as HTMLElement;
+ //click the element
+ element.click();
+}
+
+export { type ToastType, type Position, type Props, toast };
diff --git a/svelte.config.js b/svelte.config.js
new file mode 100644
index 00000000..3b3578e7
--- /dev/null
+++ b/svelte.config.js
@@ -0,0 +1,5 @@
+import { vitePreprocess } from "@astrojs/svelte";
+
+export default {
+ preprocess: vitePreprocess()
+};
diff --git a/tailwind.config.js b/tailwind.config.js
deleted file mode 100644
index 3b7e64d3..00000000
--- a/tailwind.config.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/** @type {import('tailwindcss').Config} */
-export default {
- content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
- theme: {
- colors: {
- primary: "var(--background-primary)",
- lighter: "var(--background-lighter)",
- "navbar-text-color": "var(--navbar-text-color)",
- "navbar-color": "var(--navbar-color)",
- "text-color": "var(--navbar-link-color)",
- "text-hover-color": "var(--navbar-link-hover-color)",
- input: "var(--input-background-color)",
- "input-text": "var(--input-text-color)",
- "input-border-color": "var(--input-border-color)",
- "dropdown-option-hover-color": "var(--dropdown-option-hover-color)",
- "border-color": "var(--border-color)"
- },
- extend: {}
- },
- plugins: []
-};
diff --git a/tailwind.config.mjs b/tailwind.config.mjs
new file mode 100644
index 00000000..44fd4b83
--- /dev/null
+++ b/tailwind.config.mjs
@@ -0,0 +1,24 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
+ theme: {
+ colors: {
+ primary: "var(--background-primary)",
+ lighter: "var(--background-lighter)",
+ "navbar-text-color": "var(--navbar-text-color)",
+ "navbar-color": "var(--navbar-color)",
+ "text-color": "var(--navbar-link-color)",
+ "text-hover-color": "var(--navbar-link-hover-color)",
+ input: "var(--input-background-color)",
+ "input-text": "var(--input-text-color)",
+ "input-border-color": "var(--input-border-color)",
+ "dropdown-option-hover-color": "var(--dropdown-option-hover-color)",
+ "border-color": "var(--border-color)"
+ },
+ fontFamily: {
+ roboto: "var(--font-family), Roboto"
+ },
+ extend: {}
+ },
+ plugins: []
+};
diff --git a/tsconfig.json b/tsconfig.json
index 30d42cf4..39294d75 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,13 +1,12 @@
-{
- "compilerOptions": {
- "target": "ES2020",
- "module": "ESNext",
- "moduleResolution": "bundler",
- "noEmit": true,
- "jsx": "react-jsx",
- "jsxImportSource": "preact",
- "esModuleInterop": true,
- "skipLibCheck": true,
- "paths": {}
- }
-}
+{
+ "extends": "astro/tsconfigs/strict",
+ "include": ["src"],
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "@components/*": ["src/components/*"],
+ "@layouts/*": ["src/layouts/*"],
+ "@utils/*": ["src/utils/*"]
+ }
+ }
+}
diff --git a/vite.config.ts b/vite.config.ts
deleted file mode 100644
index ad0ae528..00000000
--- a/vite.config.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-import million from "million/compiler";
-import { defineConfig } from "vite";
-import preact from "@preact/preset-vite";
-import { viteStaticCopy } from "vite-plugin-static-copy";
-import { uvPath } from "@titaniumnetwork-dev/ultraviolet";
-import { dynamicPath } from "@nebula-services/dynamic";
-//@ts-ignore
-import { epoxyPath } from "@mercuryworkshop/epoxy-transport";
-//@ts-ignore
-import { libcurlPath } from "@mercuryworkshop/libcurl-transport";
-import path from "path";
-import { createBareServer } from "@tomphttp/bare-server-node";
-import wisp from "wisp-server-node";
-import http from "http";
-import vsharp from "vite-plugin-vsharp";
-
-const __dirname = path.resolve();
-
-export default defineConfig({
- plugins: [
- viteStaticCopy({
- targets: [
- {
- src: `${uvPath}/**/*`.replace(/\\/g, "/"),
- dest: "uv",
- overwrite: false
- },
- {
- src: `${epoxyPath}/**/*`.replace(/\\/g, "/"),
- dest: "epoxy",
- overwrite: false
- },
- {
- src: `${libcurlPath}/**/*`.replace(/\\/g, "/"),
- dest: "libcurl",
- overwrite: false
- },
- {
- src: `${dynamicPath}/dynamic.*.js`.replace(/\\/g, "/"),
- dest: "dynamic",
- overwrite: false
- },
- {
- src: `${__dirname}/node_modules/localforage/dist/localforage.*.js`.replace(
- /\\/g,
- "/"
- ),
- dest: "localforage",
- overwrite: false
- }
- ]
- }),
- million.vite({ auto: true }),
- preact(),
- vsharp({
- width: 400
- })
- ],
- server: {
- proxy: {
- "/bare/": {
- target: "http://localhost:8080/bare/",
- changeOrigin: true,
- rewrite: (path) => path.replace(/^\/bare\//, "")
- },
- "/wisp/": {
- target: "http://localhost:8080/wisp/",
- changeOrigin: true,
- ws: true,
- rewrite: (path) => path.replace(/^\/wisp\//, "")
- },
- "/search": {
- target: "http://localhost:8080/search",
- changeOrigin: true,
- rewrite: (path) => path.replace(/^\/search/, "")
- }
- }
- }
-});
diff --git a/workerware b/workerware
new file mode 160000
index 00000000..c28ebbaa
--- /dev/null
+++ b/workerware
@@ -0,0 +1 @@
+Subproject commit c28ebbaacf659b570145f2ae8e1f6404d2abe8e2