├── .github
└── sources
│ └── branding.png
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── app.json
├── index.mjs
├── package-lock.json
├── package.json
├── render.yaml
├── services
├── .DS_Store
├── dynamic
│ ├── dynamic.client.js
│ ├── dynamic.client.js.map
│ ├── dynamic.config.js
│ ├── dynamic.handler.js
│ ├── dynamic.handler.js.map
│ ├── dynamic.html.js
│ ├── dynamic.html.js.map
│ ├── dynamic.worker.js
│ └── dynamic.worker.js.map
└── uv
│ ├── sw.js
│ ├── uv.bundle.js
│ ├── uv.bundle.js.map
│ ├── uv.client.js
│ ├── uv.client.js.map
│ ├── uv.config.js
│ ├── uv.handler.js
│ ├── uv.handler.js.map
│ ├── uv.sw.js
│ └── uv.sw.js.map
├── static
├── assets
│ ├── apps.json
│ ├── black.png
│ ├── blue.png
│ ├── cog.png
│ ├── favicon.ico
│ ├── game.png
│ ├── globedark.png
│ ├── green.png
│ ├── icons
│ │ ├── 1.webp
│ │ ├── 1v1-lol.webp
│ │ ├── 2048.webp
│ │ ├── 2D-Rocket-League.webp
│ │ ├── 3slices.webp
│ │ ├── 60-second-burger-run.webp
│ │ ├── 8ball.webp
│ │ ├── ADR.webp
│ │ ├── BFM.webp
│ │ ├── BP.webp
│ │ ├── C2048.webp
│ │ ├── DOOM.webp
│ │ ├── FNAF2.webp
│ │ ├── FNAF3.webp
│ │ ├── FNAFWeb.webp
│ │ ├── N64.webp
│ │ ├── NGON.webp
│ │ ├── OR.webp
│ │ ├── PS2.webp
│ │ ├── SF.webp
│ │ ├── SMB.webp
│ │ ├── SVI.webp
│ │ ├── W3Schools.webp
│ │ ├── aa.webp
│ │ ├── acww.webp
│ │ ├── addictinggames.webp
│ │ ├── adventure-capitalist.webp
│ │ ├── agario.webp
│ │ ├── ageofwar.webp
│ │ ├── akinator.webp
│ │ ├── amazon-luna.webp
│ │ ├── amazon.webp
│ │ ├── android.webp
│ │ ├── antwario.webp
│ │ ├── apex.webp
│ │ ├── aptoide.webp
│ │ ├── arrasio.webp
│ │ ├── bakeria.webp
│ │ ├── banditrip.webp
│ │ ├── basket-bros.webp
│ │ ├── basketball-legends.webp
│ │ ├── basketball-stars.webp
│ │ ├── biggiecheese.webp
│ │ ├── bigtowertinysquare.webp
│ │ ├── bitlife.webp
│ │ ├── bloonstd.webp
│ │ ├── bloonstd2.webp
│ │ ├── bloxd-io.webp
│ │ ├── book2.webp
│ │ ├── br.webp
│ │ ├── braintest.webp
│ │ ├── braintest2.webp
│ │ ├── braintest3.webp
│ │ ├── btd4.webp
│ │ ├── buckshotroulette.webp
│ │ ├── build-now.webp
│ │ ├── burritobison.webp
│ │ ├── buzzfeed.webp
│ │ ├── candybox.webp
│ │ ├── candyjump.webp
│ │ ├── canva.webp
│ │ ├── cat-ninja.webp
│ │ ├── celeste.webp
│ │ ├── characterai.webp
│ │ ├── chatgpt.webp
│ │ ├── chess.webp
│ │ ├── clickerheros.webp
│ │ ├── cluster-rush.webp
│ │ ├── cookieclicker.webp
│ │ ├── cookierunkingdom.webp
│ │ ├── coolmath.webp
│ │ ├── cr.webp
│ │ ├── crazy.webp
│ │ ├── cryzen.webp
│ │ ├── cs16.webp
│ │ ├── csgoparkour.webp
│ │ ├── cupcakeria.webp
│ │ ├── custom.webp
│ │ ├── db.webp
│ │ ├── deadshot.webp
│ │ ├── deal-or-no-deal.webp
│ │ ├── deeeepio.webp
│ │ ├── deepest-sword.webp
│ │ ├── default-g.webp
│ │ ├── diep.webp
│ │ ├── digdigio.webp
│ │ ├── discord.webp
│ │ ├── dl4.webp
│ │ ├── dm.webp
│ │ ├── doge-miner-1.webp
│ │ ├── doodlejump.webp
│ │ ├── doom2.webp
│ │ ├── dreader.webp
│ │ ├── drift-hunters.webp
│ │ ├── ds.webp
│ │ ├── duckduckgo.webp
│ │ ├── ducklife.webp
│ │ ├── dynast-io.webp
│ │ ├── earntodie2012part2.webp
│ │ ├── easports-fcmobile24.webp
│ │ ├── easports-ufc.webp
│ │ ├── espn.webp
│ │ ├── evadesio.webp
│ │ ├── evio.webp
│ │ ├── fallout2.webp
│ │ ├── fancypantsadventures.webp
│ │ ├── fancypantsadventures2.webp
│ │ ├── feedvid.webp
│ │ ├── fifa.webp
│ │ ├── fireboyandwatergirlcrystaltemple.webp
│ │ ├── fireboyandwatergirlelements.webp
│ │ ├── fireboyandwatergirlfairytales.webp
│ │ ├── fireboyandwatergirlforesttemple.webp
│ │ ├── fireboyandwatergirllighttemple.webp
│ │ ├── firefox.webp
│ │ ├── flixhq.webp
│ │ ├── florr.webp
│ │ ├── fmhy.webp
│ │ ├── fnf.webp
│ │ ├── fortnite.webp
│ │ ├── freefire.webp
│ │ ├── garticphone.webp
│ │ ├── gba.webp
│ │ ├── gc2.webp
│ │ ├── geforce-now.webp
│ │ ├── gemini.webp
│ │ ├── genshinimpact.webp
│ │ ├── getaway.webp
│ │ ├── gidd.webp
│ │ ├── github.webp
│ │ ├── gladihoppers.webp
│ │ ├── gmail.webp
│ │ ├── goal.webp
│ │ ├── golden-eye-007.webp
│ │ ├── google.webp
│ │ ├── googlebaseball.webp
│ │ ├── googlefeud.webp
│ │ ├── gswitch.webp
│ │ ├── gswitch2.webp
│ │ ├── gswitch3.webp
│ │ ├── guilded.webp
│ │ ├── gunspin.webp
│ │ ├── half-life.webp
│ │ ├── happywheels.webp
│ │ ├── hbo.webp
│ │ ├── hd.webp
│ │ ├── heartgold.webp
│ │ ├── helixjump.webp
│ │ ├── hexarena.webp
│ │ ├── hole.webp
│ │ ├── hordes.webp
│ │ ├── hw.webp
│ │ ├── idlebreakout.webp
│ │ ├── idlestartup.webp
│ │ ├── insta.webp
│ │ ├── interactive-buddy.webp
│ │ ├── isleward.webp
│ │ ├── itch.webp
│ │ ├── iv.webp
│ │ ├── jacksmith.webp
│ │ ├── jellymario.webp
│ │ ├── jetpackjoyride.webp
│ │ ├── johnnyupgrade.webp
│ │ ├── just-fall-lol.webp
│ │ ├── kiomet.webp
│ │ ├── kirby.webp
│ │ ├── kirka.webp
│ │ ├── krunker.webp
│ │ ├── learntofly3.webp
│ │ ├── lofi.webp
│ │ ├── lordz.webp
│ │ ├── lostgamerio.webp
│ │ ├── louie1.webp
│ │ ├── louie2.webp
│ │ ├── lp.webp
│ │ ├── ltf_idle.webp
│ │ ├── madalinmultiplayer.webp
│ │ ├── madalinstuntcars2.webp
│ │ ├── madalinstuntcars3.webp
│ │ ├── maddennfl24.webp
│ │ ├── marblesgarden.webp
│ │ ├── mario-kart-64.webp
│ │ ├── masked-forces.webp
│ │ ├── mc.webp
│ │ ├── melonplayground.webp
│ │ ├── mergefruit.webp
│ │ ├── messenger.webp
│ │ ├── mk48io.webp
│ │ ├── mlb.webp
│ │ ├── mm.webp
│ │ ├── mobsinc.webp
│ │ ├── moo.webp
│ │ ├── mope-io.webp
│ │ ├── mortal-kombat-4.webp
│ │ ├── movie-web.webp
│ │ ├── mrmine.webp
│ │ ├── mx3m-spooky.webp
│ │ ├── mx3m-winter.webp
│ │ ├── mx3m.webp
│ │ ├── na.webp
│ │ ├── narrowone.webp
│ │ ├── nba.webp
│ │ ├── nealfun.webp
│ │ ├── newgrounds.webp
│ │ ├── nfl.webp
│ │ ├── ng.webp
│ │ ├── nguidle.webp
│ │ ├── ninja-cat.webp
│ │ ├── now-gg.webp
│ │ ├── osm.webp
│ │ ├── outlook.webp
│ │ ├── ovo.webp
│ │ ├── papa-louie-3.webp
│ │ ├── papasburgeria.webp
│ │ ├── papascheeseria.webp
│ │ ├── papasfreezeria.webp
│ │ ├── papaspancakeria.webp
│ │ ├── papasscooperia.webp
│ │ ├── papassushiria.webp
│ │ ├── papaswingeria.webp
│ │ ├── paper-mario-64.webp
│ │ ├── paperio.webp
│ │ ├── paramount.webp
│ │ ├── parkourblock3d.webp
│ │ ├── pinterest.webp
│ │ ├── pix.webp
│ │ ├── pixel-shooter.webp
│ │ ├── pizza-tower.webp
│ │ ├── pizzeria.webp
│ │ ├── pl.webp
│ │ ├── poki.webp
│ │ ├── powerline.webp
│ │ ├── pranx.webp
│ │ ├── precision.webp
│ │ ├── proton.webp
│ │ ├── ptr.webp
│ │ ├── r6.webp
│ │ ├── rainbowobby.webp
│ │ ├── rainbowtower.webp
│ │ ├── redball1.webp
│ │ ├── redball2.webp
│ │ ├── redball4.webp
│ │ ├── redball4vol2.webp
│ │ ├── redball4vol3.webp
│ │ ├── request.webp
│ │ ├── retro.webp
│ │ ├── riddle-school.webp
│ │ ├── roblox.webp
│ │ ├── rocketbotroyale.webp
│ │ ├── rocketpult.webp
│ │ ├── rooftop.webp
│ │ ├── rooftopsnipers2.webp
│ │ ├── rs2.webp
│ │ ├── rs3.webp
│ │ ├── rs4.webp
│ │ ├── rs5.webp
│ │ ├── run3.webp
│ │ ├── sand.webp
│ │ ├── sandboxels.webp
│ │ ├── sandtrix.webp
│ │ ├── saulrun.webp
│ │ ├── scratch-among-us.webp
│ │ ├── scratch.webp
│ │ ├── shapezio.webp
│ │ ├── shell-shockers.webp
│ │ ├── showdown.webp
│ │ ├── shuttle.webp
│ │ ├── skribblio.webp
│ │ ├── slither.webp
│ │ ├── slope.webp
│ │ ├── sm63.webp
│ │ ├── sm64.webp
│ │ ├── smashkarts.webp
│ │ ├── snake.webp
│ │ ├── snap.webp
│ │ ├── snorlax.webp
│ │ ├── snowball.webp
│ │ ├── snowrider3d.webp
│ │ ├── solarsmash.webp
│ │ ├── soundcloud.webp
│ │ ├── spaceplan.webp
│ │ ├── spotify.webp
│ │ ├── ssf1.webp
│ │ ├── stabfish.webp
│ │ ├── starblastio.webp
│ │ ├── steam.webp
│ │ ├── stickman-archero-fight.webp
│ │ ├── stickmanhook.webp
│ │ ├── stompedio.webp
│ │ ├── stumble-guys.webp
│ │ ├── sugarsugar.webp
│ │ ├── super-smash-bros-64.webp
│ │ ├── supplychainlogo.webp
│ │ ├── swordbattle.webp
│ │ ├── tamingio.webp
│ │ ├── tanuki.webp
│ │ ├── telegram.webp
│ │ ├── temple-run-2.webp
│ │ ├── templeofboom.webp
│ │ ├── temu.webp
│ │ ├── territorialio.webp
│ │ ├── tetrio.webp
│ │ ├── the-simpsons-game.webp
│ │ ├── theimpossiblequiz.webp
│ │ ├── thelast-io.webp
│ │ ├── thereisnogame.webp
│ │ ├── thisissand.webp
│ │ ├── tiktok.webp
│ │ ├── timeshooter2.webp
│ │ ├── tinyfishing.webp
│ │ ├── tocabocahairsalon4.webp
│ │ ├── tocakitchen2.webp
│ │ ├── tocalifeworld.webp
│ │ ├── tpg.webp
│ │ ├── trello.webp
│ │ ├── trex-run-3D.webp
│ │ ├── tribalsio.webp
│ │ ├── tubejumpers.webp
│ │ ├── tumblr.webp
│ │ ├── tunnelrush.webp
│ │ ├── tunnelrush2.webp
│ │ ├── twistedcookingmama.webp
│ │ ├── twitch.webp
│ │ ├── twitter.webp
│ │ ├── tyranio.webp
│ │ ├── venge.webp
│ │ ├── vercel.webp
│ │ ├── vex3.webp
│ │ ├── vex4.webp
│ │ ├── vex5.webp
│ │ ├── vex6.webp
│ │ ├── vex7.webp
│ │ ├── voxiom.webp
│ │ ├── vscode.webp
│ │ ├── wattpad.webp
│ │ ├── webretro.webp
│ │ ├── whatsapp.webp
│ │ ├── wiki.webp
│ │ ├── windows96.webp
│ │ ├── wingsio.webp
│ │ ├── worldbox.webp
│ │ ├── wrassling.webp
│ │ ├── y8.webp
│ │ ├── yohoho.webp
│ │ ├── youtube.webp
│ │ ├── zombs-io.webp
│ │ └── zombs-royale.webp
│ ├── orange.png
│ ├── purple.png
│ ├── red.png
│ ├── themes.json
│ └── themes
│ │ ├── cappuccino.css
│ │ ├── frappe.css
│ │ ├── grey.css
│ │ ├── m.css
│ │ ├── macchiato.css
│ │ ├── mocha.css
│ │ └── moon.css
├── index.html
├── index.js
├── m.html
├── m.js
├── particles.js
├── sw.js
├── tabsys.js
└── themesys.js
└── vercel.json
/.github/sources/branding.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbyssServices/Abyss-Web/938df88b94cca98a560cd6b1e64209789050b694/.github/sources/branding.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Node.js
2 | node_modules/
3 | npm-debug.log
4 | yarn-error.log
5 |
6 | # Dependency directories
7 | /.pnp
8 | .pnp.js
9 |
10 | # Optional npm cache directory
11 | .npm
12 |
13 | # ESLint
14 | /.eslintcache
15 |
16 | # IDE
17 | .idea/
18 | .vscode/
19 | *.sublime-project
20 | *.sublime-workspace
21 |
22 | # Logs
23 | logs
24 | *.log
25 |
26 | # Build output
27 | /dist
28 | /build
29 |
30 | # Environment variables
31 | .env
32 | .env.local
33 | .env.development.local
34 | .env.test.local
35 | .env.production.local
36 |
37 | # Testing
38 | /coverage
39 |
40 | # Editor directories and files
41 | .editorconfig
42 | .eslintignore
43 | .eslintrc
44 | .jshintrc
45 | .prettierignore
46 | .prettierrc
47 |
48 | # code-alt's extensions
49 | .history/
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:bookworm-slim
2 | ENV NODE_ENV=production
3 |
4 | WORKDIR /app
5 |
6 | COPY ["package.json", "./"]
7 |
8 | RUN npm install
9 |
10 | COPY . .
11 |
12 | CMD [ "node", "index.js" ]
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Abyss is an advanced proxy service that provides modern unblocking for all users who use it.
4 |
5 |
6 | 
7 |
8 | > [!IMPORTANT]
9 | > If you fork this project, consider giving it a star in the original repository!
10 |
11 | **Join Our [Discord Community](https://discord.gg/goabyss) for support, more links, and an active community!**
12 |
13 | ## Features
14 |
15 | - About:Blank Cloaking
16 | - https://play.geforcenow.com
17 | - https://pc.shadow.tech/login
18 | - Tab Cloaking
19 | - Wide collection of apps & games
20 | - Clean, Easy to use UI
21 | - Inspect Element
22 | - Various Themes
23 | - Built-in Tab System
24 | - Now.gg Support
25 | - Fast Speeds
26 |
27 | ## Deployment
28 |
29 | > [!IMPORTANT]
30 | > You **cannot** deploy to static web hosts, including Netlify, Cloudflare Pages, and GitHub Pages.
31 |
32 | ### Server Deployment
33 |
34 | You must run these commands on your server:
35 | `git clone https://github.com/AbyssServices/Abyss-Web`
36 | `cd Abyss-Web`
37 | `npm install`
38 | `npm start`
39 |
40 | ### Updating
41 |
42 | `cd Abyss-Web`
43 | `git pull --force --allow-unrelated-histories`
44 |
45 |
46 |
47 |
48 | #### What happened to Replit Deployment?
49 |
50 | As of January 1st, 2024, Replit is [no longer free](https://blog.replit.com/hosting-changes). Try GitHub Codespaces instead.
51 |
52 | ### GitHub Codespaces
53 |
54 | 1. Create a GitHub account if you haven't already.
55 | 2. Click "Code" (green button) and then "Create Codespace on main."
56 | 3. In the terminal at the bottom, paste `pnpm i && pnpm start`.
57 | 4. Respond to the application popup by clicking "Make public."
58 | > [!IMPORTANT]
59 | > Make sure you click the "Make public." button, or the proxy won't function properly.
60 | 5. Access the deployed website from the ports tab.
61 | 6. For subsequent uses in the same codespace, just run `pnpm start`
62 |
63 | ### Solution for if there is no popup.
64 |
65 | 1. Run `pnpm i`, and before `pnpm start`, prepend `PORT=8080`, replacing 8080 with another port. For example, `PORT=6969 pnpm start`.
66 | 3. Go to the ports tab, Click Forward A Port, And type the port number.
67 | 4. Right-click Visibility and set Port Visibility to Public.
68 |
69 | > [!NOTE]
70 | > We are committed to making Abyss easy and personalized however, as of now we need your support in making it ad-free. Consider keeping ads so Abyss can run freely or contribute by being a supporter.
71 |
72 | ## Report Issues
73 |
74 | If you encounter problems, open an issue on GitHub, and we'll address it promptly.
75 |
76 | > [!TIP]
77 | > If you're having trouble, don't hesitate to reach out to us on [Discord](https://discord.gg/goabyss) for personalized support.
78 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "edu",
3 | "description": "?",
4 | "repository": "https://github.com/AbyssServices/Abyss-Web",
5 | "keywords": ["school", "math"],
6 | "image": "heroku/nodejs"
7 | }
8 |
--------------------------------------------------------------------------------
/index.mjs:
--------------------------------------------------------------------------------
1 | import { createBareServer } from "@tomphttp/bare-server-node";
2 | // const createBareServer = bareServerNode.createBareServer;
3 | import express from "express";
4 | import http from "http";
5 | import { dirname, join } from "path";
6 | import { hostname } from "node:os";
7 | import { fileURLToPath } from "url";
8 | import compression from 'compression';
9 | import chalk from 'chalk';
10 | import 'dotenv/config'
11 |
12 |
13 | let port = parseInt(process.env.PORT || "");
14 |
15 | if (isNaN(port)) port = 8080;
16 |
17 | const bare = createBareServer("/bare/");
18 | const app = express();
19 |
20 | const __filename = fileURLToPath(import.meta.url);
21 | const __dirname = dirname(__filename);
22 |
23 | app.use(compression());
24 | app.use(express.static(__dirname + "/static/"));
25 | app.use("/class/", express.static(__dirname + "/services/uv/"));
26 | app.use("/work/", express.static(__dirname + "/services/dynamic/"));
27 |
28 | app.use((req, res) => {
29 | res.status(404);
30 | res.send(
31 | `404 :( The page you are looking for might have been removed or does not exist. If you opened Abyss inside of Abyss, this page will also show up.
Open a new tab to continue.
`
32 | );
33 | });
34 |
35 | const server = http.createServer();
36 |
37 | server.on('error', (err) => {
38 | console.error(`ERROR: ${err}`);
39 | });
40 |
41 | server.on("request", (req, res) => {
42 | if (bare.shouldRoute(req)) {
43 | bare.routeRequest(req, res);
44 | } else {
45 | app(req, res);
46 | }
47 | });
48 |
49 | server.on("upgrade", (req, socket, head) => {
50 | if (bare.shouldRoute(req)) {
51 | bare.routeUpgrade(req, socket, head);
52 | } else {
53 | socket.end();
54 | }
55 | });
56 |
57 | server.on("listening", () => {
58 | const address = server.address();
59 | console.log(chalk.green("ABYSS: Abyss Web started."));
60 | console.log("Listening on:");
61 | console.log(`\thttp://localhost:${address.port}`);
62 | console.log(`\thttp://${hostname()}:${address.port}`);
63 | console.log(
64 | `\thttp://${
65 | address.family === "IPv6" ? `[${address.address}]` : address.address
66 | }:${address.port}`
67 | );
68 | });
69 |
70 | process.on("SIGINT", shutdown);
71 | process.on("SIGTERM", shutdown);
72 |
73 | function shutdown() {
74 | console.log("SIGTERM signal received: closing HTTP server");
75 | server.close();
76 | bare.close();
77 | process.exit(0);
78 | }
79 |
80 | server.listen({
81 | port,
82 | });
83 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "abyss",
3 | "version": "6.0.0",
4 | "description": "",
5 | "main": "index.mjs",
6 | "scripts": {
7 | "start": "node index.mjs"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "LGPL-2.0-only",
12 | "dependencies": {
13 | "@nebula-services/ultraviolet": "^1.0.1-1.patch.7",
14 | "@tomphttp/bare-server-node": "^2.0.1",
15 | "chalk": "^5.3.0",
16 | "compression": "^1.7.4",
17 | "dotenv": "^16.3.1",
18 | "eruda": "^3.0.1",
19 | "express": "^4.18.2"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/render.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | - type: web
3 | name: edu
4 | env: docker
5 | plan: free
6 |
--------------------------------------------------------------------------------
/services/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbyssServices/Abyss-Web/938df88b94cca98a560cd6b1e64209789050b694/services/.DS_Store
--------------------------------------------------------------------------------
/services/dynamic/dynamic.config.js:
--------------------------------------------------------------------------------
1 | // See documentation for more information
2 |
3 | self.__dynamic$config = {
4 | prefix: '/classes/english/',
5 | encoding: 'xor',
6 | mode: 'production',
7 | logLevel: 0,
8 | bare: {
9 | version: 2,
10 | path: '/bare/',
11 | },
12 | tab: {
13 | title: null,
14 | icon: null,
15 | ua: null,
16 | },
17 | assets: {
18 | prefix: '/work/',
19 | files: {
20 | handler: 'dynamic.handler.js',
21 | client: 'dynamic.client.js',
22 | worker: 'dynamic.worker.js',
23 | config: 'dynamic.config.js',
24 | inject: null,
25 | }
26 | },
27 | block: [
28 |
29 | ]
30 | };
31 |
--------------------------------------------------------------------------------
/services/uv/sw.js:
--------------------------------------------------------------------------------
1 | /*global UVServiceWorker,__uv$config*/
2 | /*
3 | * Stock service worker script.
4 | * Users can provide their own sw.js if they need to extend the functionality of the service worker.
5 | * Ideally, this will be registered under the scope in uv.config.js so it will not need to be modified.
6 | * However, if a user changes the location of uv.bundle.js/uv.config.js or sw.js is not relative to them, they will need to modify this script locally.
7 | */
8 | importScripts('uv.bundle.js');
9 | importScripts('uv.config.js');
10 | importScripts(__uv$config.sw || 'uv.sw.js');
11 |
12 | const sw = new UVServiceWorker();
13 |
14 | self.addEventListener('fetch', (event) => event.respondWith(sw.fetch(event)));
15 |
--------------------------------------------------------------------------------
/services/uv/uv.config.js:
--------------------------------------------------------------------------------
1 | /*global Ultraviolet*/
2 | self.__uv$config = {
3 | prefix: '/classes/math/',
4 | bare: '/bare/',
5 | encodeUrl: Ultraviolet.codec.xor.encode,
6 | decodeUrl: Ultraviolet.codec.xor.decode,
7 | handler: '/class/uv.handler.js',
8 | client: '/class/uv.client.js',
9 | bundle: '/class/uv.bundle.js',
10 | config: '/class/uv.config.js',
11 | sw: '/class/uv.sw.js',
12 | };
13 |
--------------------------------------------------------------------------------
/services/uv/uv.sw.js:
--------------------------------------------------------------------------------
1 | (()=>{var p=self.Ultraviolet,x=["cross-origin-embedder-policy","cross-origin-opener-policy","cross-origin-resource-policy","content-security-policy","content-security-policy-report-only","expect-ct","feature-policy","origin-isolation","strict-transport-security","upgrade-insecure-requests","x-content-type-options","x-download-options","x-frame-options","x-permitted-cross-domain-policies","x-powered-by","x-xss-protection"],w=["GET","HEAD"],b=class extends p.EventEmitter{constructor(t=__uv$config){super(),t.bare||(t.bare="/bare/"),t.prefix||(t.prefix="/service/"),this.config=t;let i=(Array.isArray(t.bare)?t.bare:[t.bare]).map(e=>new URL(e,location).toString());this.address=i[~~(Math.random()*i.length)],this.bareClient=new p.BareClient(this.address)}async fetch({request:t}){let i;try{if(!t.url.startsWith(location.origin+this.config.prefix))return await fetch(t);let e=new p(this.config,this.address);typeof this.config.construct=="function"&&this.config.construct(e,"service");let a=await e.cookie.db();e.meta.origin=location.origin,e.meta.base=e.meta.url=new URL(e.sourceUrl(t.url));let r=new g(t,this,e,w.includes(t.method.toUpperCase())?null:await t.blob());if(e.meta.url.protocol==="blob:"&&(r.blob=!0,r.base=r.url=new URL(r.url.pathname)),t.referrer&&t.referrer.startsWith(location.origin)){let n=new URL(e.sourceUrl(t.referrer));(r.headers.origin||e.meta.url.origin!==n.origin&&t.mode==="cors")&&(r.headers.origin=n.origin),r.headers.referer=n.href}let l=await e.cookie.getCookies(a)||[],c=e.cookie.serialize(l,e.meta,!1);r.headers["user-agent"]=navigator.userAgent,c&&(r.headers.cookie=c);let f=new m(r,null,null);if(this.emit("request",f),f.intercepted)return f.returnValue;i=r.blob?"blob:"+location.origin+r.url.pathname:r.url;let h=await this.bareClient.fetch(i,{headers:r.headers,method:r.method,body:r.body,credentials:r.credentials,mode:location.origin!==r.address.origin?"cors":r.mode,cache:r.cache,redirect:r.redirect,proxyIp:this.config.proxyIp,proxyPort:this.config.proxyPort}),s=new y(r,h),d=new m(s,null,null);if(this.emit("beforemod",d),d.intercepted)return d.returnValue;for(let n of x)s.headers[n]&&delete s.headers[n];if(s.headers.location&&(s.headers.location=e.rewriteUrl(s.headers.location)),t.destination==="document"){let n=s.headers["content-disposition"];if(!/\s*?((inline|attachment);\s*?)filename=/i.test(n)){let u=/^\s*?attachment/i.test(n)?"attachment":"inline",[v]=new URL(h.finalURL).pathname.split("/").slice(-1);s.headers["content-disposition"]=`${u}; filename=${JSON.stringify(v)}`}}if(s.headers["set-cookie"]&&(Promise.resolve(e.cookie.setCookies(s.headers["set-cookie"],a,e.meta)).then(()=>{self.clients.matchAll().then(function(n){n.forEach(function(u){u.postMessage({msg:"updateCookies",url:e.meta.url.href})})})}),delete s.headers["set-cookie"]),s.body)switch(t.destination){case"script":case"worker":{let n=[e.bundleScript,e.clientScript,e.configScript,e.handlerScript].map(u=>JSON.stringify(u)).join(",");s.body=`if (!self.__uv && self.importScripts) { ${e.createJsInject(this.address,this.bareClient.manfiest,e.cookie.serialize(l,e.meta,!0),t.referrer)} importScripts(${n}); }
2 | `,s.body+=e.js.rewrite(await h.text())}break;case"style":s.body=e.rewriteCSS(await h.text());break;case"iframe":case"document":S(e.meta.url,s.headers["content-type"]||"")&&(s.body=e.rewriteHtml(await h.text(),{document:!0,injectHead:e.createHtmlInject(e.handlerScript,e.bundleScript,e.clientScript,e.configScript,this.address,this.bareClient.manfiest,e.cookie.serialize(l,e.meta,!0),t.referrer)}))}return r.headers.accept==="text/event-stream"&&(s.headers["content-type"]="text/event-stream"),crossOriginIsolated&&(s.headers["Cross-Origin-Embedder-Policy"]="require-corp"),this.emit("response",d),d.intercepted?d.returnValue:new Response(s.body,{headers:s.headers,status:s.status,statusText:s.statusText})}catch(e){return["document","iframe"].includes(t.destination)?(console.error(e),O(e,i,this.address)):new Response(void 0,{status:500})}}static Ultraviolet=p};self.UVServiceWorker=b;var y=class{constructor(t,i){this.request=t,this.raw=i,this.ultraviolet=t.ultraviolet,this.headers={};for(let e in i.rawHeaders)this.headers[e.toLowerCase()]=i.rawHeaders[e];this.status=i.status,this.statusText=i.statusText,this.body=i.body}get url(){return this.request.url}get base(){return this.request.base}set base(t){this.request.base=t}},g=class{constructor(t,i,e,a=null){this.ultraviolet=e,this.request=t,this.headers=Object.fromEntries(t.headers.entries()),this.method=t.method,this.address=i.address,this.body=a||null,this.cache=t.cache,this.redirect=t.redirect,this.credentials="omit",this.mode=t.mode==="cors"?t.mode:"same-origin",this.blob=!1}get url(){return this.ultraviolet.meta.url}set url(t){this.ultraviolet.meta.url=t}get base(){return this.ultraviolet.meta.base}set base(t){this.ultraviolet.meta.base=t}};function S(o,t=""){return(p.mime.contentType(t||o.pathname)||"text/html").split(";")[0]==="text/html"}var m=class{#e;#t;constructor(t={},i=null,e=null){this.#e=!1,this.#t=null,this.data=t,this.target=i,this.that=e}get intercepted(){return this.#e}get returnValue(){return this.#t}respondWith(t){this.#t=t,this.#e=!0}};function C(o,t){let i=new URL(o),e=`remoteHostname.textContent = ${JSON.stringify(i.hostname)};bareServer.href = ${JSON.stringify(t)};uvHostname.textContent = ${JSON.stringify(location.hostname)};reload.addEventListener("click", () => location.reload());uvVersion.textContent = ${JSON.stringify("1.0.11.patch.7")};`;return`Error This site can\u2019t be reached \u2019s server IP address could not be found.
Try:
Verifying you entered the correct address Clearing the site data Contacting 's administrator Verifying the Bare server isn't censored Reload Ultraviolet v
19 |
20 |
21 |
22 |
23 |
24 |
25 |
abyss
26 |
discord.gg/goabyss
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/static/m.js:
--------------------------------------------------------------------------------
1 | var particlesConfig = {"particles":{"number":{"value":67,"density":{"enable":true,"value_area":800}},"color":{"value":"#ffffff"},"shape":{"type":"circle","stroke":{"width":1,"color":"#000000"},"polygon":{"nb_sides":5},"image":{"src":"img/github.svg","width":100,"height":100}},"opacity":{"value":1,"random":false,"anim":{"enable":false,"speed":1,"opacity_min":0.1,"sync":false}},"size":{"value":14,"random":true,"anim":{"enable":false,"speed":40,"size_min":0.1,"sync":false}},"line_linked":{"enable":false,"distance":150,"color":"#ffffff","opacity":0.4,"width":1},"move":{"enable":true,"speed":1.5,"direction":"none","random":true,"straight":false,"out_mode":"out","bounce":false,"attract":{"enable":false,"rotateX":600,"rotateY":1200}}},"interactivity":{"detect_on":"canvas","events":{"onhover":{"enable":false,"mode":"repulse"},"onclick":{"enable":false,"mode":"push"},"resize":true},"modes":{"grab":{"distance":400,"line_linked":{"opacity":1}},"bubble":{"distance":400,"size":40,"duration":2,"opacity":8,"speed":3},"repulse":{"distance":200,"duration":0.4},"push":{"particles_nb":4},"remove":{"particles_nb":2}}},"retina_detect":true}
2 | particlesJS("particles-js", particlesConfig)
3 | const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
4 | if (!isMobile) {
5 | window.location.href = "/";
6 | }
7 | function go(url) {
8 | if (!/^(https?:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,30}/i.test(url)) {
9 | url = 'https://www.google.com/search?q=' + url;
10 | } else if (!/^(https?:\/\/)/.test(url)) {
11 | url = "https://" + url;
12 | }
13 | window.location.href = '/classes/math/' + __uv$config.encodeUrl(url);
14 | }
15 |
16 | async function worker() {
17 | return await navigator.serviceWorker.register("/sw.js", {
18 | scope: "/classes",
19 | });
20 | }
21 |
22 | document.addEventListener("DOMContentLoaded", async function () {
23 | await worker();
24 | workerLoaded = true;
25 | });
26 |
--------------------------------------------------------------------------------
/static/sw.js:
--------------------------------------------------------------------------------
1 | importScripts("/work/dynamic.config.js");
2 | importScripts("/work/dynamic.worker.js");
3 | importScripts("/class/uv.bundle.js");
4 | importScripts("/class/uv.config.js");
5 | importScripts("/class/uv.sw.js"); // override because the support for UV is complete dogshit
6 |
7 | const uv = new UVServiceWorker();
8 | const dynamic = new Dynamic();
9 |
10 | self.dynamic = dynamic;
11 |
12 | self.addEventListener("fetch", (event) => {
13 | event.respondWith(
14 | (async function () {
15 | if (await dynamic.route(event)) {
16 | return await dynamic.fetch(event);
17 | }
18 |
19 | if (event.request.url.startsWith(location.origin + "/classes/math/")) {
20 | return await uv.fetch(event);
21 | }
22 |
23 | return await fetch(event.request);
24 | })()
25 | );
26 | });
27 |
28 |
--------------------------------------------------------------------------------
/static/tabsys.js:
--------------------------------------------------------------------------------
1 | // OP TAB SYSTEM V2.2.0
2 |
3 | // LICENSE:
4 | /*
5 |
6 | Copyright (c) 2023 Code-Alt
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a copy
9 | of this software and associated documentation files (the "Software"), to deal
10 | in the Software without restriction, including without limitation the rights
11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | copies of the Software, and to permit persons to whom the Software is
13 | furnished to do so, subject to the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be included in
16 | all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | THE SOFTWARE.
25 |
26 | */
27 |
28 | // DOCS:
29 |
30 | // here are some prerequisites:
31 | // you must have a tab container, a btn container, a tab template, and a btn template, and a search bar.
32 | // btw this might be hard to set up, set up your own classes and CSS until you find it satisfactory.
33 |
34 | // new TabSystem() - Initializes the TabSystem class, used for holding all the information about the tab system, and it's functions.
35 | // TabSystem.addTab(tab) - Adds a tab to the tab system. Returns the tab.
36 | // TabSystem.getTabTemplate() - Returns the tab template.
37 | // TabSystem.getBtnTemplate() - Returns the tab button template.
38 | // TabSystem.createTabBtn(id) - Creates a tab button with the specified id. Returns the tab button.
39 | // TabSystem.createTabFrame(id) - Creates a tab frame with the specified id. Returns the tab frame.
40 | // TabSystem.setActiveTab(tab) - Sets the active tab to the specified tab.
41 | // TabSystem.getActiveTab() - Returns the active tab.
42 | // TabSystem.getTabs() - Returns all tabs.
43 | // TabSystem.getTabCount() - Returns the amount of tabs.
44 | // TabSystem.genRanId() - Generates a random id. Returns the id.
45 | // TabSystem.deleteTab(tab, force) - Deletes the specified tab. If force is true, it will delete the tab even if it's the last tab.
46 | // TabSystem.deleteTabs(tabs, force) - Deletes the specified tabs. If force is true, it will delete the tabs even if it's the last tab.
47 | // TabSystem.deleteAllTabs() - Deletes all tabs.
48 | // TabSystem.deleteAllTabsExcept(tab) - Deletes all tabs except the specified tab.
49 | // TabSystem.deleteAllTabsExceptThese(tabs) - Deletes all tabs except the specified tabs.
50 | // new Tab() - Initializes the Tab class, used for holding all the information about the tab frame and the button used to activate it.
51 | // Tab.getConnectedElement() - Returns the connected element.
52 | // Tab.getTabElement() - Returns the tab element.
53 | // Tab.setTabElement(tabElement) - Sets the tab element.
54 | // Tab.setConnectedElement(connectedElement) - Sets the connected element.
55 |
56 | var dp = "Starting Page";
57 | var conf = {};
58 | var mainTS;
59 | var _OPTabSys_callbacks = {
60 | tabChange: [],
61 | tabAdd: [],
62 | tabDelete: [],
63 | };
64 |
65 | class TabSystem {
66 | constructor(object) {
67 | this.config = {
68 | tabContainer:
69 | object.tabContainer || document.getElementById("tabContainer"),
70 | tabTemplate: object.tabTemplate || document.getElementById("tabTemplate"),
71 | btnTemplate: object.btnTemplate || document.getElementById("btnTemplate"),
72 | tabBtnContainer:
73 | object.tabBtnContainer || document.getElementById("tabBtnContainer"),
74 | URLBar: object.URLBar || document.getElementById("adrbar"),
75 | defaultPlaceholder: object.defaultPlaceholder || "Starting Page",
76 | closePlaceholder: object.closePlaceholder || "No tab open",
77 | tabActiveClass: object.tabActiveClass || "op-tabs-active",
78 | };
79 | conf = this.config;
80 | dp = this.config.defaultPlaceholder;
81 | this.tabs = [];
82 | this.tabCount = 0;
83 | this.activeTab = null;
84 | this.config.tabTemplate.style.display = "none";
85 | this.config.btnTemplate.style.display = "none";
86 | mainTS = this;
87 | }
88 |
89 | on(event, callback) {
90 | switch (event) {
91 | case "tabChange":
92 | if (_OPTabSys_callbacks == null) _OPTabSys_callbacks = {};
93 | if (_OPTabSys_callbacks.tabChange == null)
94 | _OPTabSys_callbacks.tabChange = [];
95 | _OPTabSys_callbacks.tabChange.push(callback);
96 | break;
97 | case "tabAdd":
98 | if (_OPTabSys_callbacks == null) _OPTabSys_callbacks = {};
99 | if (_OPTabSys_callbacks.tabAdd == null) _OPTabSys_callbacks.tabAdd = [];
100 | _OPTabSys_callbacks.tabAdd.push(callback);
101 | break;
102 | case "tabDelete":
103 | if (_OPTabSys_callbacks == null) _OPTabSys_callbacks = {};
104 | if (_OPTabSys_callbacks.tabDelete == null)
105 | _OPTabSys_callbacks.tabDelete = [];
106 | _OPTabSys_callbacks.tabDelete.push(callback);
107 | break;
108 | default:
109 | return console.error("Invalid event!");
110 | }
111 | }
112 |
113 | addTab(tab) {
114 | this.tabs.push(tab);
115 | this.tabCount++;
116 | if (_OPTabSys_callbacks != null) {
117 | if (_OPTabSys_callbacks.tabAdd != null) {
118 | for (var i = 0; i < _OPTabSys_callbacks.tabAdd.length; i++) {
119 | _OPTabSys_callbacks.tabAdd[i](tab);
120 | }
121 | }
122 | }
123 | return tab;
124 | }
125 |
126 | getTabTemplate() {
127 | return this.config.tabTemplate;
128 | }
129 |
130 | getBtnTemplate() {
131 | return this.config.btnTemplate;
132 | }
133 |
134 | createTabBtn(id) {
135 | const btn = this.getBtnTemplate().cloneNode(true);
136 | if (id == null) id = "";
137 | btn.id = id;
138 | btn.style = btn.style.toString().replace(/display:( )*none(;){0,1}/g, "");
139 | this.config.tabBtnContainer.appendChild(btn);
140 | btn.style.width = "0px";
141 | btn.style.opacity = "0";
142 | setTimeout(() => {
143 | btn.style.width = "235px";
144 | btn.style.opacity = "1";
145 | }, 0);
146 | return btn;
147 | }
148 |
149 | createTabFrame(id) {
150 | const frame = this.getTabTemplate().cloneNode(true);
151 | if (id == null) id = "";
152 | frame.id = id;
153 | frame.style.display = "none";
154 | this.config.tabContainer.appendChild(frame);
155 | return frame;
156 | }
157 |
158 | setActiveTab(tab) {
159 | if (_OPTabSys_callbacks != null) {
160 | if (_OPTabSys_callbacks.tabChange != null) {
161 | for (var i = 0; i < _OPTabSys_callbacks.tabChange.length; i++) {
162 | _OPTabSys_callbacks.tabChange[i](tab);
163 | }
164 | }
165 | }
166 | if (!this.tabs.includes(tab) && tab != null) {
167 | this.addTab(tab);
168 | }
169 | if (this.activeTab != null) {
170 | this.activeTab.getConnectedElement().classList.remove(this.config.tabActiveClass);
171 | this.activeTab.setSearchBarContent(this.config.URLBar.value);
172 | this.activeTab.setPlaceholder(this.config.URLBar.placeholder);
173 | }
174 | this.config.URLBar.value = "";
175 | if (tab != null && tab.getSearchBarContent()) {
176 | this.config.URLBar.value = tab.getSearchBarContent();
177 | }
178 | this.activeTab = tab;
179 | if (tab != null && this.activeTab.getPlaceholder()) {
180 | this.config.URLBar.placeholder = this.activeTab.getPlaceholder();
181 | }
182 | if (this.activeTab == null) {
183 | this.config.URLBar.placeholder = this.config.closePlaceholder;
184 | }
185 | for (var t = 0; t < this.tabs.length; t++) {
186 | if (this.tabs[t] == tab && tab != null) {
187 | if (this.tabs[t].tabElement != null) {
188 | this.tabs[t].tabElement.style.display = "initial";
189 | }
190 | if (this.tabs[t].connectedElement != null) {
191 | this.tabs[t].connectedElement.classList.add(this.config.tabActiveClass);
192 | }
193 | } else {
194 | if (this.tabs[t].tabElement != null && tab != null) {
195 | this.tabs[t].tabElement.style.display = "none";
196 | }
197 | if (this.tabs[t].connectedElement != null && tab != null) {
198 | this.tabs[t].connectedElement.classList.remove(this.config.tabActiveClass);
199 | }
200 | }
201 | }
202 | }
203 |
204 | getActiveTab() {
205 | return this.activeTab;
206 | }
207 |
208 | getTabs() {
209 | return this.tabs;
210 | }
211 |
212 | getTabCount() {
213 | return this.tabCount;
214 | }
215 |
216 | genRanId() {
217 | return Date.now() + Math.floor(Math.random() * 1000000000);
218 | }
219 |
220 | deleteTab(tab, force) {
221 | for (var i = 0; i < this.tabs.length; i++) {
222 | if (this.tabs[i] == tab) {
223 | if (this.tabs[i] == this.activeTab) {
224 | if (this.tabs[i - 1] != null) {
225 | this.setActiveTab(this.tabs[i - 1]);
226 | } else if (this.tabs[i + 1] != null) {
227 | this.setActiveTab(this.tabs[i + 1]);
228 | } else {
229 | if (force != true) {
230 | return alert("You can't delete the last tab!");
231 | } else {
232 | this.setActiveTab(null);
233 | }
234 | }
235 | }
236 | this.tabs[i].connectedElement.remove();
237 | this.tabs[i].tabElement.remove();
238 | this.tabs.splice(i, 1);
239 | this.tabCount--;
240 | if (_OPTabSys_callbacks != null) {
241 | if (_OPTabSys_callbacks.tabDelete != null) {
242 | for (var tC = 0; tC < _OPTabSys_callbacks.tabDelete.length; tC++) {
243 | _OPTabSys_callbacks.tabDelete[tC](this.activeTab);
244 | }
245 | }
246 | }
247 | break;
248 | }
249 | }
250 | }
251 |
252 | deleteTabs(tabs) {
253 | const tabsToDelete = tabs.slice();
254 | for (let i = 0; i < tabsToDelete.length; i++) {
255 | const tab = tabsToDelete[i];
256 | if (tab === this.activeTab) {
257 | if (this.tabs[i - 1]) {
258 | this.setActiveTab(this.tabs[i - 1]);
259 | } else if (this.tabs[i + 1]) {
260 | this.setActiveTab(this.tabs[i + 1]);
261 | } else {
262 | this.setActiveTab(null);
263 | }
264 | }
265 | tab.connectedElement.remove();
266 | tab.tabElement.remove();
267 | this.tabs.splice(this.tabs.indexOf(tab), 1);
268 | this.tabCount--;
269 | }
270 | if (_OPTabSys_callbacks?.tabDelete) {
271 | _OPTabSys_callbacks.tabDelete.forEach((callback) =>
272 | callback(this.activeTab)
273 | );
274 | }
275 | }
276 |
277 | deleteAllTabs() {
278 | this.deleteTabs(this.tabs);
279 | }
280 |
281 | deleteAllTabsExcept(tab) {
282 | const tabsToDelete = this.tabs.slice();
283 | tabsToDelete.splice(tabsToDelete.indexOf(tab), 1);
284 | this.deleteTabs(tabsToDelete);
285 | }
286 |
287 | deleteAllTabsExceptThese(tabs) {
288 | const tabsToDelete = this.tabs.slice();
289 | tabsToDelete.forEach((tab) => {
290 | if (tabs.includes(tab)) {
291 | tabsToDelete.splice(tabsToDelete.indexOf(tab), 1);
292 | }
293 | });
294 | this.deleteTabs(tabsToDelete);
295 | }
296 |
297 | getConfig() {
298 | return this.config;
299 | }
300 | }
301 |
302 | class Tab {
303 | constructor(connectedElement, tabFrame, searchBarContent, placeholder) {
304 | this.connectedElement =
305 | connectedElement || mainTS.createTabBtn(mainTS.genRanId());
306 | this.tabElement = tabFrame || mainTS.createTabFrame(mainTS.genRanId());
307 | if (searchBarContent == null) searchBarContent = "";
308 | this.searchBarContent = searchBarContent;
309 | if (placeholder == null) placeholder = dp;
310 | this.placeholder = placeholder;
311 | this.connectedElement.addEventListener("click", () => {
312 | if (window.tryClose) {
313 | this.connectedElement.style.width="0px";
314 | this.connectedElement.style.opacity="0";
315 | window.setTimeout(() => {
316 | mainTS.deleteTab(this, window.allowForce);
317 | window.tryClose = false;
318 | }, 200);
319 | return;
320 | }
321 | mainTS.setActiveTab(this);
322 | });
323 | }
324 |
325 | getConnectedElement() {
326 | return this.connectedElement;
327 | }
328 |
329 | getTabElement() {
330 | return this.tabElement;
331 | }
332 |
333 | setSearchBarContent(searchBarContent) {
334 | this.searchBarContent = searchBarContent;
335 | }
336 |
337 | getSearchBarContent() {
338 | return this.searchBarContent;
339 | }
340 |
341 | findFirstIFrame() {
342 | return this.tabElement.querySelector("iframe");
343 | }
344 |
345 | hasIFrame() {
346 | if (this.findIFrame() != null) {
347 | return true;
348 | } else {
349 | return false;
350 | }
351 | }
352 |
353 | setPlaceholder(placeholder) {
354 | this.placeholder = placeholder;
355 | }
356 |
357 | getPlaceholder() {
358 | return this.placeholder;
359 | }
360 | }
361 |
362 | window.TabSystem = TabSystem;
363 | window.Tab = Tab;
364 | window.allowForce = true;
365 |
--------------------------------------------------------------------------------
/static/themesys.js:
--------------------------------------------------------------------------------
1 | class ThemeSystem {
2 | constructor() {
3 | this.config = {}; // is there even a need for this
4 | this.themes = [];
5 | this.themeCount = 0;
6 | this.activeTheme = null;
7 | this.lastTheme = null;
8 | }
9 |
10 | getThemeFromName(name) {
11 | for (let i = 0; i < this.themes.length; i++) {
12 | if (this.themes[i].getName() == name) {
13 | return this.themes[i];
14 | }
15 | }
16 | }
17 |
18 | addTheme(theme) {
19 | for (let i = 0; i < this.themes.length; i++) {
20 | if (this.themes[i].getName() == theme.getName()) {
21 | console.error(
22 | "A theme with the name " + theme.getName() + " already exists!"
23 | );
24 | return;
25 | }
26 | }
27 | if (this.lastTheme != theme) {
28 | this.themes.push(theme);
29 | this.themeCount++;
30 | }
31 | return theme;
32 | }
33 |
34 | setActiveTheme(theme) {
35 | if (this.activeTheme != null) {
36 | this.activeTheme.disable();
37 | }
38 | this.activeTheme = theme;
39 | this.activeTheme.apply();
40 | }
41 |
42 | getActiveTheme() {
43 | return this.activeTheme;
44 | }
45 |
46 | getThemes() {
47 | return this.themes;
48 | }
49 |
50 | getThemeCount() {
51 | return this.themeCount;
52 | }
53 |
54 | genRanId() {
55 | return (
56 | Math.random().toString(36).substring(2, 15) +
57 | Math.random().toString(36).substring(2, 15)
58 | );
59 | }
60 |
61 | deleteTheme(theme) {
62 | if (this.themeCount > 1 || force == true) {
63 | for (let i = 0; i < this.themes.length; i++) {
64 | if (this.themes[i].id == theme.id) {
65 | this.themes.splice(i, 1);
66 | this.themeCount--;
67 | if (this.activeTheme.id == theme.id) {
68 | this.setActiveTheme(this.themes[0]);
69 | }
70 | }
71 | }
72 | }
73 | }
74 |
75 | deleteThemes(themes) {
76 | if (this.themeCount > 1) {
77 | for (let i = 0; i < themes.length; i++) {
78 | this.deleteTheme(themes[i]);
79 | }
80 | }
81 | }
82 |
83 | genCSS(css) {
84 | var style = document.createElement("style");
85 | style.innerHTML = css;
86 | style.disabled = true;
87 | document.head.appendChild(style);
88 | return style;
89 | }
90 |
91 | genCSSFile(url, enabled) {
92 | for (let i = 0; i < this.themes.length; i++) {
93 | if (
94 | this.themes[i].getCSSElem() &&
95 | this.themes[i].getCSSElem().href == url
96 | ) {
97 | console.error("A theme with the url " + url + " already exists!");
98 | return;
99 | }
100 | }
101 | var link = document.createElement("link");
102 | link.rel = "stylesheet";
103 | link.href = url;
104 | document.head.appendChild(link);
105 | link.disabled = true;
106 | if (enabled) link.disabled = false;
107 | return link;
108 | }
109 |
110 | getConfig() {
111 | return this.config;
112 | }
113 | }
114 |
115 | class Theme {
116 | constructor(elem, name) {
117 | if (typeof elem == "object") {
118 | this.csselem = elem;
119 | } else {
120 | this.url = elem;
121 | }
122 | this.store = elem;
123 | this.name = name;
124 | // check for a duplicate theme
125 | for (let i = 0; i < tHs.getThemes().length; i++) {
126 | if (tHs.getThemes()[i].getName() == this.name) {
127 | console.error(
128 | "A theme with the name " + this.name + " already exists!"
129 | );
130 | delete this;
131 | return;
132 | }
133 | }
134 | }
135 |
136 | apply() {
137 | if (typeof this.store == "object") {
138 | this.csselem.disabled = false;
139 | } else {
140 | this.csselem = tHs.genCSSFile(this.url, true);
141 | }
142 | }
143 |
144 | disable() {
145 | if (typeof this.store == "object") {
146 | this.csselem.disabled = true;
147 | } else {
148 | this.csselem.remove();
149 | this.csselem = null;
150 | }
151 | }
152 |
153 | setName(name) {
154 | this.name = name;
155 | }
156 |
157 | getName() {
158 | return this.name;
159 | }
160 |
161 | getURL() {
162 | return this.url;
163 | }
164 |
165 | setURL(url) {
166 | this.url = url;
167 | }
168 |
169 | getCSSElem() {
170 | return this.csselem;
171 | }
172 |
173 | setCSSElem(elem) {
174 | this.csselem = elem;
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "builds": [
3 | {
4 | "src": "index.mjs",
5 | "use": "@vercel/node"
6 | }
7 | ],
8 | "routes": [
9 | {
10 | "src": "/(.*)",
11 | "dest": "index.mjs"
12 | }
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------