Add path aliases, optimize adding i18n to a page, and general cleanup.

This commit is contained in:
wearrrrr 2024-04-01 12:22:02 -05:00
parent ece900b353
commit e54858620b
25 changed files with 125 additions and 311 deletions

View file

@ -14,7 +14,7 @@ import dotenv from "dotenv";
import cookieParser from "cookie-parser"; import cookieParser from "cookie-parser";
import wisp from "wisp-server-node"; import wisp from "wisp-server-node";
import fs from "node:fs"; import fs from "node:fs";
import fetch from 'node-fetch'; import fetch from "node-fetch";
dotenv.config(); dotenv.config();
const LICENSE_SERVER_URL = "https://license.mercurywork.shop/validate?license="; const LICENSE_SERVER_URL = "https://license.mercurywork.shop/validate?license=";
@ -137,8 +137,8 @@ app.use("/custom-favicon", async (req, res) => {
const response = await fetch(url).then((apiRes) => apiRes.buffer()); const response = await fetch(url).then((apiRes) => apiRes.buffer());
res.send(response); res.send(response);
} catch (err) { } catch (err) {
console.log(err) console.log(err);
res.send("Error") res.send("Error");
} }
}); });
app.use("/", express.static("dist/client/")); app.use("/", express.static("dist/client/"));

View file

@ -4,8 +4,7 @@
? factory(exports) ? factory(exports)
: typeof define === "function" && define.amd : typeof define === "function" && define.amd
? define(["exports"], factory) ? define(["exports"], factory)
: ((global = : ((global = typeof globalThis !== "undefined" ? globalThis : global || self),
typeof globalThis !== "undefined" ? globalThis : global || self),
factory((global.BareMod = {}))); factory((global.BareMod = {})));
})(this, function (exports) { })(this, function (exports) {
"use strict"; "use strict";
@ -17,12 +16,12 @@
const WebSocket = globalThis.WebSocket; const WebSocket = globalThis.WebSocket;
const WebSocketFields = { const WebSocketFields = {
prototype: { prototype: {
send: WebSocket.prototype.send send: WebSocket.prototype.send,
}, },
CLOSED: WebSocket.CLOSED, CLOSED: WebSocket.CLOSED,
CLOSING: WebSocket.CLOSING, CLOSING: WebSocket.CLOSING,
CONNECTING: WebSocket.CONNECTING, CONNECTING: WebSocket.CONNECTING,
OPEN: WebSocket.OPEN OPEN: WebSocket.OPEN,
}; };
class BareError extends Error { class BareError extends Error {
@ -441,7 +440,7 @@
throw new BareError(400, { throw new BareError(400, {
code: "INVALID_BARE_HEADER", code: "INVALID_BARE_HEADER",
id: `request.headers.${header}`, id: `request.headers.${header}`,
message: `Value didn't begin with semi-colon.` message: `Value didn't begin with semi-colon.`,
}); });
} }
const id = parseInt(header.slice(prefix.length + 1)); const id = parseInt(header.slice(prefix.length + 1));
@ -473,16 +472,7 @@
async init() { async init() {
this.ready = true; this.ready = true;
} }
connect( connect(url, origin, protocols, requestHeaders, onopen, onmessage, onclose, onerror) {
url,
origin,
protocols,
requestHeaders,
onopen,
onmessage,
onclose,
onerror
) {
const ws = new WebSocket(this.ws); const ws = new WebSocket(this.ws);
const cleanup = () => { const cleanup = () => {
ws.removeEventListener("close", closeListener); ws.removeEventListener("close", closeListener);
@ -495,13 +485,10 @@
cleanup(); cleanup();
// ws.binaryType is irrelevant when sending text // ws.binaryType is irrelevant when sending text
if (typeof event.data !== "string") if (typeof event.data !== "string")
throw new TypeError( throw new TypeError("the first websocket message was not a text frame");
"the first websocket message was not a text frame"
);
const message = JSON.parse(event.data); const message = JSON.parse(event.data);
// finally // finally
if (message.type !== "open") if (message.type !== "open") throw new TypeError("message was not of open type");
throw new TypeError("message was not of open type");
// onMeta({ // onMeta({
// protocol: message.protocol, // protocol: message.protocol,
// setCookies: message.setCookies, // setCookies: message.setCookies,
@ -526,7 +513,7 @@
remote: url.toString(), remote: url.toString(),
protocols, protocols,
headers: requestHeaders, headers: requestHeaders,
forwardHeaders: [] forwardHeaders: [],
}) })
); );
// ); // );
@ -540,16 +527,13 @@
const options = { const options = {
credentials: "omit", credentials: "omit",
method: method, method: method,
signal signal,
}; };
if (body !== undefined) { if (body !== undefined) {
options.body = body; options.body = body;
} }
options.headers = this.createBareHeaders(remote, headers); options.headers = this.createBareHeaders(remote, headers);
const response = await fetch( const response = await fetch(this.http + "?cache=" + md5(remote.toString()), options);
this.http + "?cache=" + md5(remote.toString()),
options
);
const readResponse = await this.readBareResponse(response); const readResponse = await this.readBareResponse(response);
// const result: Response & Partial<BareResponse> = new Response( // const result: Response & Partial<BareResponse> = new Response(
// statusEmpty.includes(readResponse.status!) ? undefined : response.body, // statusEmpty.includes(readResponse.status!) ? undefined : response.body,
@ -566,7 +550,7 @@
body: response.body, body: response.body,
headers: readResponse.headers, headers: readResponse.headers,
status: readResponse.status, status: readResponse.status,
statusText: readResponse.statusText statusText: readResponse.statusText,
}; };
} }
async readBareResponse(response) { async readBareResponse(response) {
@ -583,13 +567,7 @@
if (xBareHeaders !== null) result.headers = JSON.parse(xBareHeaders); if (xBareHeaders !== null) result.headers = JSON.parse(xBareHeaders);
return result; return result;
} }
createBareHeaders( createBareHeaders(remote, bareHeaders, forwardHeaders = [], passHeaders = [], passStatus = []) {
remote,
bareHeaders,
forwardHeaders = [],
passHeaders = [],
passStatus = []
) {
const headers = new Headers(); const headers = new Headers();
headers.set("x-bare-url", remote.toString()); headers.set("x-bare-url", remote.toString());
headers.set("x-bare-headers", JSON.stringify(bareHeaders)); headers.set("x-bare-headers", JSON.stringify(bareHeaders));
@ -608,4 +586,4 @@
} }
exports.BareClient = ClientV3; exports.BareClient = ClientV3;
}); });

View file

@ -1,6 +1,6 @@
importScripts("/libcurl/index.js"); importScripts("/libcurl/index.js");
importScripts("/epoxy/index.js"); importScripts("/epoxy/index.js");
importScripts("/bare_transport.js") importScripts("/bare_transport.js");
importScripts("/uv/uv.bundle.js"); importScripts("/uv/uv.bundle.js");
importScripts("/uv.config.js"); importScripts("/uv.config.js");
importScripts(__uv$config.sw); importScripts(__uv$config.sw);

View file

@ -1,10 +1,10 @@
<script src="/uv/uv.bundle.js" transition:persist is:inline></script> <script src="/uv/uv.bundle.js" transition:persist is:inline defer></script>
<script src="/uv.config.js" transition:persist is:inline></script> <script src="/uv.config.js" transition:persist is:inline defer></script>
<script src="/epoxy/index.js" transition:persist is:inline></script> <script src="/epoxy/index.js" transition:persist is:inline defer></script>
<script src="/libcurl/index.js" transition:persist is:inline></script> <script src="/libcurl/index.js" transition:persist is:inline defer></script>
<script src="/bare_transport.js" transition:persist is:inline></script> <script src="/bare_transport.js" transition:persist is:inline defer></script>
<script> <script>
import { initTransport } from "./ts/TransportManager"; import { initTransport } from "./ts/TransportManager";
let form = document.querySelector("form"); let form = document.querySelector("form");
let input = document.querySelector("input"); let input = document.querySelector("input");
@ -39,7 +39,7 @@ import { initTransport } from "./ts/TransportManager";
if (!rammerheadSession) { if (!rammerheadSession) {
let session = await fetch("/newsession"); let session = await fetch("/newsession");
let sessionID = await session.text(); let sessionID = await session.text();
await fetch("/editsession?id=" + sessionID + "&enableShuffling=0"); await fetch("/editsession?id=" + sessionID + "&enableShuffling=0");
// Now save it in a cookie that expires in 72 hours. // Now save it in a cookie that expires in 72 hours.
document.cookie = `rammerhead-session=${sessionID}; max-age=${60 * 60 * 72}; path=/`; document.cookie = `rammerhead-session=${sessionID}; max-age=${60 * 60 * 72}; path=/`;
// Now add an origin_proxy cookie for our domain // Now add an origin_proxy cookie for our domain
@ -61,7 +61,10 @@ import { initTransport } from "./ts/TransportManager";
else if (!(url.startsWith("https://") || url.startsWith("http://"))) url = "http://" + url; else if (!(url.startsWith("https://") || url.startsWith("http://"))) url = "http://" + url;
if (openWith) { if (openWith) {
let openWithParsed = JSON.parse(openWith); let openWithParsed = JSON.parse(openWith);
if (openWithParsed.value === "newTab" || (currentProxy && JSON.parse(currentProxy).value === "rammerhead")) { if (
openWithParsed.value === "newTab" ||
(currentProxy && JSON.parse(currentProxy).value === "rammerhead")
) {
window.open(await getProxyURL(), "_blank"); window.open(await getProxyURL(), "_blank");
return; return;
} }
@ -113,7 +116,12 @@ import { initTransport } from "./ts/TransportManager";
const boundIFrameLoad = iframeLoad.bind(null, iframe, loadingContent, topbar, closeButton); const boundIFrameLoad = iframeLoad.bind(null, iframe, loadingContent, topbar, closeButton);
iframe.addEventListener("load", boundIFrameLoad); iframe.addEventListener("load", boundIFrameLoad);
function iframeLoad(iframe: HTMLIFrameElement, loadingContent: HTMLElement, topbar: HTMLDivElement, closeButton: HTMLButtonElement) { function iframeLoad(
iframe: HTMLIFrameElement,
loadingContent: HTMLElement,
topbar: HTMLDivElement,
closeButton: HTMLButtonElement
) {
loadingContent.style.opacity = "0"; loadingContent.style.opacity = "0";
iframe.style.opacity = "1"; iframe.style.opacity = "1";
topbar.style.opacity = "1"; topbar.style.opacity = "1";
@ -216,11 +224,16 @@ import { initTransport } from "./ts/TransportManager";
if (iframe) { if (iframe) {
if (iframe.contentDocument) { if (iframe.contentDocument) {
let favicon = let favicon =
iframe.contentDocument.querySelector("link[rel='icon']") as HTMLLinkElement || (iframe.contentDocument.querySelector("link[rel='icon']") as HTMLLinkElement) ||
iframe.contentDocument.querySelector("link[rel*='icon']") as HTMLLinkElement; (iframe.contentDocument.querySelector("link[rel*='icon']") as HTMLLinkElement);
if(favicon && favicon.href) { if (favicon && favicon.href) {
if (proxiedFavicon.src == `${window.location.origin}/custom-favicon?url=${encodeURIComponent(favicon.href)}` || hasErrored) return; if (
} proxiedFavicon.src ==
`${window.location.origin}/custom-favicon?url=${encodeURIComponent(favicon.href)}` ||
hasErrored
)
return;
}
if (favicon) { if (favicon) {
proxiedFavicon.src = `/custom-favicon?url=${encodeURIComponent(favicon.href)}`; proxiedFavicon.src = `/custom-favicon?url=${encodeURIComponent(favicon.href)}`;
proxiedFavicon.addEventListener("error", () => { proxiedFavicon.addEventListener("error", () => {
@ -247,6 +260,5 @@ import { initTransport } from "./ts/TransportManager";
} }
topbarTitle.innerText = iframe.contentDocument.title; topbarTitle.innerText = iframe.contentDocument.title;
} }
} }
</script> </script>

View file

@ -1,5 +1,7 @@
--- ---
import Input from "../Input.astro"; import Input from "@components/UI/Input.astro";
import { i18n } from "@i18n/utils";
const t = i18n.inferLangUseTranslations(Astro.url);
const presetCloaks = [ const presetCloaks = [
{ {
@ -8,8 +10,7 @@ const presetCloaks = [
}, },
{ {
cloakTitle: "Google", cloakTitle: "Google",
favicon: favicon: "/icons/google.png",
"/icons/google.png",
}, },
{ {
cloakTitle: "Canvas", cloakTitle: "Canvas",
@ -21,8 +22,7 @@ const presetCloaks = [
}, },
{ {
cloakTitle: "Classlink", cloakTitle: "Classlink",
favicon: favicon: "/icons/classlink.png",
"/icons/classlink.png",
}, },
{ {
cloakTitle: "Google Drive", cloakTitle: "Google Drive",
@ -58,7 +58,7 @@ const presetCloaks = [
<div class="cloak-custom-override"> <div class="cloak-custom-override">
<Input inputName="cloak-custom-name" placeholder="Custom Name" height="30px" /> <Input inputName="cloak-custom-name" placeholder="Custom Name" height="30px" />
<Input inputName="cloak-custom-favicon" placeholder="Custom Favicon" height="30px" /> <Input inputName="cloak-custom-favicon" placeholder="Custom Favicon" height="30px" />
<button id="cloak-custom-button">Update Cloak</button> <button id="cloak-custom-button">{t("settings.cloaking.updateCloak")}</button>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,7 +1,6 @@
--- ---
import { getLangFromUrl, useTranslations } from "../../i18n/utils"; import { i18n } from "@i18n/utils";
const lang = getLangFromUrl(Astro.url); const t = i18n.inferLangUseTranslations(Astro.url);
const t = useTranslations(lang);
--- ---
<div class="settings-container"> <div class="settings-container">

View file

@ -1,9 +1,8 @@
--- ---
import Dropdown from "../Dropdown.astro"; import Dropdown from "@components/UI/Dropdown.astro";
import { getLangFromUrl, useTranslations } from "../../i18n/utils"; import { i18n } from "@i18n/utils";
const lang = getLangFromUrl(Astro.url); const t = i18n.inferLangUseTranslations(Astro.url);
const t = useTranslations(lang);
const themeList = [ const themeList = [
{ name: t("settings.customization.theme.Alu"), value: "alu" }, { name: t("settings.customization.theme.Alu"), value: "alu" },

View file

@ -1,10 +1,9 @@
--- ---
import Input from "../Input.astro"; import Input from "@components/UI/Input.astro";
import Dropdown from "../Dropdown.astro"; import Dropdown from "@components/UI/Dropdown.astro";
import { getLangFromUrl, useTranslations } from "../../i18n/utils"; import { i18n } from "@i18n/utils";
const lang = getLangFromUrl(Astro.url); const t = i18n.inferLangUseTranslations(Astro.url);
const t = useTranslations(lang);
const proxyList = [ const proxyList = [
{ name: t("settings.proxy.auto"), value: "auto" }, { name: t("settings.proxy.auto"), value: "auto" },

View file

@ -1,12 +1,12 @@
--- ---
import ProxyTab from "./SettingsContent/ProxyTab.astro"; import ProxyTab from "./SettingsContent/ProxyTab.astro";
import CustomizationTab from "./SettingsContent/CustomizationTab.astro"; import CustomizationTab from "./SettingsContent/CustomizationTab.astro";
import { getLangFromUrl, useTranslations } from "../i18n/utils";
import CloakingTab from "./SettingsContent/CloakingTab.astro"; import CloakingTab from "./SettingsContent/CloakingTab.astro";
import CreditsTab from "./SettingsContent/CreditsTab.astro"; import CreditsTab from "./SettingsContent/CreditsTab.astro";
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang); import { i18n } from "@i18n/utils";
const lang = i18n.getLangFromUrl(Astro.url);
const t = i18n.useTranslations(lang);
--- ---
<div class="content-hidden"> <div class="content-hidden">

View file

@ -1,192 +0,0 @@
---
const { inputID } = Astro.props;
---
<label class="switch">
<input id={inputID} checked="" type="checkbox" />
<div class="slider">
<div class="circle">
<svg
class="cross"
xml:space="preserve"
style="enable-background:new 0 0 512 512"
viewBox="0 0 365.696 365.696"
y="0"
x="0"
height="6"
width="6"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
xmlns="http://www.w3.org/2000/svg">
<g>
<path
data-original="#000000"
fill="currentColor"
d="M243.188 182.86 356.32 69.726c12.5-12.5 12.5-32.766 0-45.247L341.238 9.398c-12.504-12.503-32.77-12.503-45.25 0L182.86 122.528 69.727 9.374c-12.5-12.5-32.766-12.5-45.247 0L9.375 24.457c-12.5 12.504-12.5 32.77 0 45.25l113.152 113.152L9.398 295.99c-12.503 12.503-12.503 32.769 0 45.25L24.48 356.32c12.5 12.5 32.766 12.5 45.247 0l113.132-113.132L295.99 356.32c12.503 12.5 32.769 12.5 45.25 0l15.081-15.082c12.5-12.504 12.5-32.77 0-45.25zm0 0"
></path>
</g>
</svg>
<svg
class="checkmark"
xml:space="preserve"
style="enable-background:new 0 0 512 512"
viewBox="0 0 24 24"
y="0"
x="0"
height="10"
width="10"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
xmlns="http://www.w3.org/2000/svg">
<g>
<path
class=""
data-original="#000000"
fill="currentColor"
d="M9.707 19.121a.997.997 0 0 1-1.414 0l-5.646-5.647a1.5 1.5 0 0 1 0-2.121l.707-.707a1.5 1.5 0 0 1 2.121 0L9 14.171l9.525-9.525a1.5 1.5 0 0 1 2.121 0l.707.707a1.5 1.5 0 0 1 0 2.121z"
></path>
</g>
</svg>
</div>
</div>
</label>
<style>
.switch {
--switch-width: 46px;
--switch-height: 24px;
--switch-bg: rgb(131, 131, 131);
--switch-checked-bg: rgb(0, 218, 80);
--switch-offset: calc((var(--switch-height) - var(--circle-diameter)) / 2);
--switch-transition: all 0.2s cubic-bezier(0.27, 0.2, 0.25, 1.51);
--circle-diameter: 18px;
--circle-bg: #fff;
--circle-shadow: 1px 1px 2px rgba(146, 146, 146, 0.45);
--circle-checked-shadow: -1px 1px 2px rgba(163, 163, 163, 0.45);
--circle-transition: var(--switch-transition);
--icon-transition: all 0.2s cubic-bezier(0.27, 0.2, 0.25, 1.51);
--icon-cross-color: var(--switch-bg);
--icon-cross-size: 6px;
--icon-checkmark-color: var(--switch-checked-bg);
--icon-checkmark-size: 10px;
--effect-width: calc(var(--circle-diameter) / 2);
--effect-height: calc(var(--effect-width) / 2 - 1px);
--effect-bg: var(--circle-bg);
--effect-border-radius: 1px;
--effect-transition: all 0.2s ease-in-out;
}
.switch input {
display: none;
}
.switch {
display: inline-block;
}
.switch svg {
-webkit-transition: var(--icon-transition);
-o-transition: var(--icon-transition);
transition: var(--icon-transition);
position: absolute;
height: auto;
}
.switch .checkmark {
width: var(--icon-checkmark-size);
color: var(--icon-checkmark-color);
-webkit-transform: scale(0);
-ms-transform: scale(0);
transform: scale(0);
}
.switch .cross {
width: var(--icon-cross-size);
color: var(--icon-cross-color);
}
.slider {
-webkit-box-sizing: border-box;
box-sizing: border-box;
width: var(--switch-width);
height: var(--switch-height);
background: var(--switch-bg);
border-radius: 999px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
position: relative;
-webkit-transition: var(--switch-transition);
-o-transition: var(--switch-transition);
transition: var(--switch-transition);
cursor: pointer;
}
.circle {
width: var(--circle-diameter);
height: var(--circle-diameter);
background: var(--circle-bg);
border-radius: inherit;
-webkit-box-shadow: var(--circle-shadow);
box-shadow: var(--circle-shadow);
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-transition: var(--circle-transition);
-o-transition: var(--circle-transition);
transition: var(--circle-transition);
z-index: 1;
position: absolute;
left: var(--switch-offset);
}
.slider::before {
content: "";
position: absolute;
width: var(--effect-width);
height: var(--effect-height);
left: calc(var(--switch-offset) + (var(--effect-width) / 2));
background: var(--effect-bg);
border-radius: var(--effect-border-radius);
-webkit-transition: var(--effect-transition);
-o-transition: var(--effect-transition);
transition: var(--effect-transition);
}
/* actions */
.switch input:checked + .slider {
background: var(--switch-checked-bg);
}
.switch input:checked + .slider .checkmark {
-webkit-transform: scale(1);
-ms-transform: scale(1);
transform: scale(1);
}
.switch input:checked + .slider .cross {
-webkit-transform: scale(0);
-ms-transform: scale(0);
transform: scale(0);
}
.switch input:checked + .slider::before {
left: calc(100% - var(--effect-width) - (var(--effect-width) / 2) - var(--switch-offset));
}
.switch input:checked + .slider .circle {
left: calc(100% - var(--circle-diameter) - var(--switch-offset));
-webkit-box-shadow: var(--circle-checked-shadow);
box-shadow: var(--circle-checked-shadow);
}
</style>

View file

@ -1,9 +1,8 @@
--- ---
import { getLangFromUrl, useTranslations } from "../i18n/utils"; import { i18n } from "@i18n/utils";
import Link from "./Link.astro"; import Link from "./Link.astro";
import WaveSVG from "./WaveSVG.astro"; import WaveSVG from "../WaveSVG.astro";
const lang = getLangFromUrl(Astro.url); const t = i18n.inferLangUseTranslations(Astro.url);
const t = useTranslations(lang);
--- ---
<div class="footer"> <div class="footer">

View file

@ -1,7 +1,7 @@
--- ---
import { getLangFromUrl, useTranslations } from "../i18n/utils"; import { i18n } from "@i18n/utils";
const lang = getLangFromUrl(Astro.url); const lang = i18n.getLangFromUrl(Astro.url);
const t = useTranslations(lang); const t = i18n.useTranslations(lang);
--- ---
<div class="top-header"> <div class="top-header">

View file

@ -12,10 +12,12 @@ declare global {
} }
} }
type transportConfig = { type transportConfig =
wisp: string; | {
wasm?: string; wisp: string;
} | string; wasm?: string;
}
| string;
export const wispURLDefault = export const wispURLDefault =
(location.protocol === "https:" ? "wss://" : "ws://") + location.host + "/wisp/"; (location.protocol === "https:" ? "wss://" : "ws://") + location.host + "/wisp/";
@ -40,12 +42,11 @@ export default class TransportManager {
updateTransport() { updateTransport() {
try { try {
this.setTransport(JSON.parse(localStorage.getItem("alu__selectedTransport")!).value); this.setTransport(JSON.parse(localStorage.getItem("alu__selectedTransport")!).value);
console.log(this.transport) console.log(this.transport);
} catch { } catch {
console.log("Failed to update transport! Falling back to old transport.") console.log("Failed to update transport! Falling back to old transport.");
this.setTransport(this.transport); this.setTransport(this.transport);
} }
} }
getTransport() { getTransport() {
@ -82,5 +83,4 @@ export async function initTransport() {
resolve(null); resolve(null);
}); });
}); });
} }

View file

@ -54,6 +54,7 @@
"settings.cloaking": "Cloaking", "settings.cloaking": "Cloaking",
"settings.cloaking.subtext": "Change how your tab looks...", "settings.cloaking.subtext": "Change how your tab looks...",
"settings.cloaking.updateCloak": "Update Cloak",
"settings.credits": "Credits", "settings.credits": "Credits",
"settings.credits.mochaandmacchiatothemes": "Mocha & Macchiato Themes", "settings.credits.mochaandmacchiatothemes": "Mocha & Macchiato Themes",

View file

@ -54,6 +54,7 @@
"settings.cloaking": "クローキング", "settings.cloaking": "クローキング",
"settings.cloaking.subtext": "タブの外観を変更します...", "settings.cloaking.subtext": "タブの外観を変更します...",
"settings.cloaking.updateCloak": "クロークを更新",
"settings.credits": "クレジット", "settings.credits": "クレジット",
"settings.credits.mochaandmacchiatothemes": "モカとマキアートテーマ", "settings.credits.mochaandmacchiatothemes": "モカとマキアートテーマ",

View file

@ -2,16 +2,23 @@ import { ui, defaultLang } from "./ui";
export const STATIC_PATHS = [{ params: { lang: "en" } }, { params: { lang: "jp" } }]; export const STATIC_PATHS = [{ params: { lang: "en" } }, { params: { lang: "jp" } }];
export function getLangFromUrl(url: URL) { function getLangFromUrl(url: URL) {
// comma lol // comma lol
const [, lang] = url.pathname.split("/"); const [, lang] = url.pathname.split("/");
if (lang in ui) return lang as keyof typeof ui; if (lang in ui) return lang as keyof typeof ui;
return defaultLang; return defaultLang;
} }
export function useTranslations(lang: keyof typeof ui) { function inferLangUseTranslations(url: URL) {
const lang = getLangFromUrl(url);
return useTranslations(lang);
}
function useTranslations(lang: keyof typeof ui) {
return function t(translationKey: keyof (typeof ui)[typeof defaultLang]) { return function t(translationKey: keyof (typeof ui)[typeof defaultLang]) {
if (ui[lang][translationKey]) return ui[lang][translationKey]; if (ui[lang][translationKey]) return ui[lang][translationKey];
else return ui[defaultLang][translationKey]; else return ui[defaultLang][translationKey];
}; };
} }
export const i18n = { getLangFromUrl, useTranslations, inferLangUseTranslations };

View file

@ -1,11 +1,11 @@
--- ---
import { ViewTransitions } from "astro:transitions"; import { ViewTransitions } from "astro:transitions";
import Header from "../components/Header.astro"; import Header from "@components/UI/Header.astro";
import Footer from "../components/Footer.astro"; import Footer from "@components/UI/Footer.astro";
import ThemeLoader from "../components/ThemeLoader.astro"; import ThemeLoader from "@components/ThemeLoader.astro";
import CloakLoader from "../components/CloakLoader.astro"; import CloakLoader from "@components/CloakLoader.astro";
import WelcomeLogging from "../components/WelcomeLogging.astro"; import WelcomeLogging from "@components/WelcomeLogging.astro";
import UVRegistrar from "../components/ProxyRegistrar.astro"; import ProxyRegistrar from "@components/ProxyRegistrar.astro";
type Preload = { type Preload = {
href: string; href: string;
@ -69,7 +69,7 @@ const { title, optionalPreloads } = Astro.props;
<Header /> <Header />
<slot transition:animate={"fade"} /> <slot transition:animate={"fade"} />
<WelcomeLogging /> <WelcomeLogging />
<UVRegistrar /> <ProxyRegistrar />
<Footer /> <Footer />
<style is:global> <style is:global>
:root { :root {

View file

@ -1,11 +1,10 @@
--- ---
import Layout from "../../layouts/Layout.astro"; import Layout from "../../layouts/Layout.astro";
import games from "../../json/games.json"; import games from "../../json/games.json";
import GameItem from "../../components/GameItem.astro"; import GameItem from "@components/GameItem.astro";
import { STATIC_PATHS, getLangFromUrl, useTranslations } from "../../i18n/utils"; import { STATIC_PATHS, i18n } from "@i18n/utils";
const lang = getLangFromUrl(Astro.url); const t = i18n.inferLangUseTranslations(Astro.url);
const t = useTranslations(lang);
export function getStaticPaths() { export function getStaticPaths() {
return STATIC_PATHS; return STATIC_PATHS;

View file

@ -1,10 +1,9 @@
--- ---
import Layout from "../../layouts/Layout.astro"; import Layout from "../../layouts/Layout.astro";
import { STATIC_PATHS, getLangFromUrl, useTranslations } from "../../i18n/utils"; import { STATIC_PATHS, i18n } from "@i18n/utils";
import Link from "../../components/Link.astro"; import Link from "@components/UI/Link.astro";
const lang = getLangFromUrl(Astro.url); const t = i18n.inferLangUseTranslations(Astro.url);
const t = useTranslations(lang);
export function getStaticPaths() { export function getStaticPaths() {
return STATIC_PATHS; return STATIC_PATHS;
@ -63,11 +62,11 @@ export function getStaticPaths() {
</div> </div>
</Layout> </Layout>
<script> <script>
import { TransportMgr } from "../../components/ts/TransportManager"; import { TransportMgr } from "@components/ts/TransportManager";
document.addEventListener("astro:after-swap", () => { document.addEventListener("astro:after-swap", () => {
console.log("Updating transport...") console.log("Updating transport...");
TransportMgr.updateTransport(); TransportMgr.updateTransport();
}) });
type Suggestion = { type Suggestion = {
phrase: string; phrase: string;
}; };
@ -79,7 +78,7 @@ export function getStaticPaths() {
let request = await fetch("/search?query=" + url); let request = await fetch("/search?query=" + url);
let data = await request.json(); let data = await request.json();
searchSuggestions.innerHTML = ""; searchSuggestions.innerHTML = "";
data.map((suggestion: Suggestion) => { data.map((suggestion: Suggestion) => {
let suggestionElement = document.createElement("div"); let suggestionElement = document.createElement("div");
// For some reason css classes weren't working T^T. // For some reason css classes weren't working T^T.
suggestionElement.style.cursor = "pointer"; suggestionElement.style.cursor = "pointer";
@ -131,7 +130,7 @@ export function getStaticPaths() {
timeout = setTimeout(() => { timeout = setTimeout(() => {
cb(...args); cb(...args);
}, delay); }, delay);
} };
} }
urlInput.addEventListener("keyup", async () => { urlInput.addEventListener("keyup", async () => {

View file

@ -1,10 +1,9 @@
--- ---
import SettingsTablist from "../../components/SettingsTablist.astro"; import SettingsTablist from "@components/SettingsTablist.astro";
import Layout from "../../layouts/Layout.astro"; import Layout from "../../layouts/Layout.astro";
import { STATIC_PATHS, getLangFromUrl, useTranslations } from "../../i18n/utils"; import { STATIC_PATHS, i18n } from "@i18n/utils";
const lang = getLangFromUrl(Astro.url); const t = i18n.inferLangUseTranslations(Astro.url);
const t = useTranslations(lang);
export function getStaticPaths() { export function getStaticPaths() {
return STATIC_PATHS; return STATIC_PATHS;

View file

@ -8,7 +8,6 @@ import { ViewTransitions } from "astro:transitions";
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<ViewTransitions /> <ViewTransitions />
<script> <script>
if (localStorage.getItem("alu__selectedLanguage") === null) window.location.href = "/en/";
let currentLang = localStorage.getItem("alu__selectedLanguage"); let currentLang = localStorage.getItem("alu__selectedLanguage");
if (currentLang) { if (currentLang) {
try { try {
@ -28,6 +27,14 @@ import { ViewTransitions } from "astro:transitions";
localStorage.clear(); localStorage.clear();
window.location.reload(); window.location.reload();
} }
} else {
if (navigator.language.includes("ja")) {
localStorage.setItem("alu__selectedLanguage", JSON.stringify({ value: "jp" }));
window.location.href = "/jp/";
} else {
localStorage.setItem("alu__selectedLanguage", JSON.stringify({ value: "en" }));
window.location.href = "/en/";
}
} }
</script> </script>
</head> </head>

View file

@ -1,4 +1,11 @@
{ {
"extends": "astro/tsconfigs/strict", "extends": "astro/tsconfigs/strict",
"exclude": ["dist/**", "node_modules/**", "public/games/**", ".eslint.cjs"] "exclude": ["dist/**", "node_modules/**", "public/games/**", ".eslint.cjs"],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@components/*": ["src/components/*"],
"@i18n/*": ["src/i18n/*"]
}
}
} }