restructured and simplified favicon

This commit is contained in:
Niki Wix Skaarup 2025-04-12 21:14:09 +02:00
parent 259ccfe851
commit 08c127f637
Signed by: nikiskaarup
GPG key ID: FC2F1B116F6E788C
28 changed files with 320 additions and 260 deletions

View file

@ -35,5 +35,4 @@ COPY --from=install /temp/prod/node_modules node_modules
COPY --from=prerelease /app/ . COPY --from=prerelease /app/ .
# run the app # run the app
ENTRYPOINT [ "bun", "start" ]
ENTRYPOINT [ "bun", "run", "start" ]

View file

@ -4,7 +4,7 @@
"": { "": {
"name": "userscripts", "name": "userscripts",
"dependencies": { "dependencies": {
"@tailwindcss/cli": "4.1.1", "@tailwindcss/cli": "4.1.3",
"bun-plugin-svelte": "^0.0.6", "bun-plugin-svelte": "^0.0.6",
"bun-plugin-tailwind": "^0.0.15", "bun-plugin-tailwind": "^0.0.15",
"tailwindcss": "^4.1.3", "tailwindcss": "^4.1.3",
@ -19,7 +19,7 @@
"prettier-plugin-tailwindcss": "^0.6.11", "prettier-plugin-tailwindcss": "^0.6.11",
}, },
"peerDependencies": { "peerDependencies": {
"typescript": "^5.8.2", "typescript": "^5.8.3",
}, },
}, },
}, },
@ -94,33 +94,33 @@
"@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.5", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ=="], "@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.5", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ=="],
"@tailwindcss/cli": ["@tailwindcss/cli@4.1.1", "", { "dependencies": { "@parcel/watcher": "^2.5.1", "@tailwindcss/node": "4.1.1", "@tailwindcss/oxide": "4.1.1", "enhanced-resolve": "^5.18.1", "mri": "^1.2.0", "picocolors": "^1.1.1", "tailwindcss": "4.1.1" }, "bin": { "tailwindcss": "dist/index.mjs" } }, "sha512-e+k52zGEjaClimmt/85UwF43NIvB0r0PLXRId2QYUwmbExuU3XPhfBzitdrEKZOTM1goH1Vs4wrNxnqDn8ITQA=="], "@tailwindcss/cli": ["@tailwindcss/cli@4.1.3", "", { "dependencies": { "@parcel/watcher": "^2.5.1", "@tailwindcss/node": "4.1.3", "@tailwindcss/oxide": "4.1.3", "enhanced-resolve": "^5.18.1", "mri": "^1.2.0", "picocolors": "^1.1.1", "tailwindcss": "4.1.3" }, "bin": { "tailwindcss": "dist/index.mjs" } }, "sha512-irQW1LhBCi8O7OPrDVTyo6IZFqUDukGkcqOIxoU9d7zSOxU5LZQ1EB1KA981xmZpPIIfaowgdia8FSxaQrBonQ=="],
"@tailwindcss/node": ["@tailwindcss/node@4.1.1", "", { "dependencies": { "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "lightningcss": "1.29.2", "tailwindcss": "4.1.1" } }, "sha512-xvlh4pvfG/bkv0fEtJDABAm1tjtSmSyi2QmS4zyj1EKNI1UiOYiUq1IphSwDsNJ5vJ9cWEGs4rJXpUdCN2kujQ=="], "@tailwindcss/node": ["@tailwindcss/node@4.1.3", "", { "dependencies": { "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "lightningcss": "1.29.2", "tailwindcss": "4.1.3" } }, "sha512-H/6r6IPFJkCfBJZ2dKZiPJ7Ueb2wbL592+9bQEl2r73qbX6yGnmQVIfiUvDRB2YI0a3PWDrzUwkvQx1XW1bNkA=="],
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.1", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.1", "@tailwindcss/oxide-darwin-arm64": "4.1.1", "@tailwindcss/oxide-darwin-x64": "4.1.1", "@tailwindcss/oxide-freebsd-x64": "4.1.1", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.1", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.1", "@tailwindcss/oxide-linux-arm64-musl": "4.1.1", "@tailwindcss/oxide-linux-x64-gnu": "4.1.1", "@tailwindcss/oxide-linux-x64-musl": "4.1.1", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.1", "@tailwindcss/oxide-win32-x64-msvc": "4.1.1" } }, "sha512-7+YBgnPQ4+jv6B6WVOerJ6WOzDzNJXrRKDts674v6TKAqFqYRr9+EBtSziO7nNcwQ8JtoZNMeqA+WJDjtCM/7w=="], "@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.3", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.3", "@tailwindcss/oxide-darwin-arm64": "4.1.3", "@tailwindcss/oxide-darwin-x64": "4.1.3", "@tailwindcss/oxide-freebsd-x64": "4.1.3", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.3", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.3", "@tailwindcss/oxide-linux-arm64-musl": "4.1.3", "@tailwindcss/oxide-linux-x64-gnu": "4.1.3", "@tailwindcss/oxide-linux-x64-musl": "4.1.3", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.3", "@tailwindcss/oxide-win32-x64-msvc": "4.1.3" } }, "sha512-t16lpHCU7LBxDe/8dCj9ntyNpXaSTAgxWm1u2XQP5NiIu4KGSyrDJJRlK9hJ4U9yJxx0UKCVI67MJWFNll5mOQ=="],
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.1", "", { "os": "android", "cpu": "arm64" }, "sha512-gTyRzfdParpoCU1yyUC/iN6XK6T0Ra4bDlF8Aeul5NP9cLzKEZDogdNVNGv5WZmCDkVol7qlex7TMmcfytMmmw=="], "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.3", "", { "os": "android", "cpu": "arm64" }, "sha512-cxklKjtNLwFl3mDYw4XpEfBY+G8ssSg9ADL4Wm6//5woi3XGqlxFsnV5Zb6v07dxw1NvEX2uoqsxO/zWQsgR+g=="],
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-dI0QbdMWBvLB3MtaTKetzUKG9CUUQow8JSP4Nm+OxVokeZ+N+f1OmZW/hW1LzMxpx9RQCBgSRL+IIvKRat5Wdg=="], "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-mqkf2tLR5VCrjBvuRDwzKNShRu99gCAVMkVsaEOFvv6cCjlEKXRecPu9DEnxp6STk5z+Vlbh1M5zY3nQCXMXhw=="],
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-2Y+NPQOTRBCItshPgY/CWg4bKi7E9evMg4bgdb6h9iZObCZLOe3doPcuSxGS3DB0dKyMFKE8pTdWtFUbxZBMSA=="], "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-7sGraGaWzXvCLyxrc7d+CCpUN3fYnkkcso3rCzwUmo/LteAl2ZGCDlGvDD8Y/1D3ngxT8KgDj1DSwOnNewKhmg=="],
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-N97NGMsB/7CHShbc5ube4dcsW/bYENkBrg8yWi8ieN9boYVRdw3cZviVryV/Nfu9bKbBV9kUvduFF2qBI7rEqg=="], "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-E2+PbcbzIReaAYZe997wb9rId246yDkCwAakllAWSGqe6VTg9hHle67hfH6ExjpV2LSK/siRzBUs5wVff3RW9w=="],
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.1", "", { "os": "linux", "cpu": "arm" }, "sha512-33Lk6KbHnUZbXqza6RWNFo9wqPQ4+H5BAn1CkUUfC1RZ1vYbyDN6+iJPj53wmnWJ3mhRI8jWt3Jt1fO02IVdUQ=="], "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.3", "", { "os": "linux", "cpu": "arm" }, "sha512-GvfbJ8wjSSjbLFFE3UYz4Eh8i4L6GiEYqCtA8j2Zd2oXriPuom/Ah/64pg/szWycQpzRnbDiJozoxFU2oJZyfg=="],
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-LyW35RzSUy+80WYScv03HKasAUmMFDaSbNpWfk1gG5gEE9kuRGnDzSrqMoLAmY/kzMCYP/1kqmUiAx8EFLkI2A=="], "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-35UkuCWQTeG9BHcBQXndDOrpsnt3Pj9NVIB4CgNiKmpG8GnCNXeMczkUpOoqcOhO6Cc/mM2W7kaQ/MTEENDDXg=="],
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-1KPnDMlHdqjPTUSFjx55pafvs8RZXRgxfeRgUrukwDKkuj7gFk28vW3Mx65YdiugAc9NWs3VgueZWaM1Po6uGw=="], "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-dm18aQiML5QCj9DQo7wMbt1Z2tl3Giht54uVR87a84X8qRtuXxUqnKQkRDK5B4bCOmcZ580lF9YcoMkbDYTXHQ=="],
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.1", "", { "os": "linux", "cpu": "x64" }, "sha512-4WdzA+MRlsinEEE6yxNMLJxpw0kE9XVipbAKdTL8BeUpyC2TdA3TL46lBulXzKp3BIxh3nqyR/UCqzl5o+3waQ=="], "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.3", "", { "os": "linux", "cpu": "x64" }, "sha512-LMdTmGe/NPtGOaOfV2HuO7w07jI3cflPrVq5CXl+2O93DCewADK0uW1ORNAcfu2YxDUS035eY2W38TxrsqngxA=="],
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.1", "", { "os": "linux", "cpu": "x64" }, "sha512-q7Ugbw3ARcjCW2VMUYrcMbJ6aMQuWPArBBE2EqC/swPZTdGADvMQSlvR0VKusUM4HoSsO7ZbvcZ53YwR57+AKw=="], "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.3", "", { "os": "linux", "cpu": "x64" }, "sha512-aalNWwIi54bbFEizwl1/XpmdDrOaCjRFQRgtbv9slWjmNPuJJTIKPHf5/XXDARc9CneW9FkSTqTbyvNecYAEGw=="],
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-0KpqsovgHcIzm7eAGzzEZsEs0/nPYXnRBv+aPq/GehpNQuE/NAQu+YgZXIIof+VflDFuyXOEnaFr7T5MZ1INhA=="], "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-PEj7XR4OGTGoboTIAdXicKuWl4EQIjKHKuR+bFy9oYN7CFZo0eu74+70O4XuERX4yjqVZGAkCdglBODlgqcCXg=="],
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.1", "", { "os": "win32", "cpu": "x64" }, "sha512-B1mjeXNS26kBOHv5sXARf6Wd0PWHV9x1TDlW0ummrBUOUAxAy5wcy4Nii1wzNvCdvC448hgiL06ylhwAbNthmg=="], "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.3", "", { "os": "win32", "cpu": "x64" }, "sha512-T8gfxECWDBENotpw3HR9SmNiHC9AOJdxs+woasRZ8Q/J4VHN0OMs7F+4yVNZ9EVN26Wv6mZbK0jv7eHYuLJLwA=="],
"@types/bun": ["@types/bun@1.2.9", "", { "dependencies": { "bun-types": "1.2.9" } }, "sha512-epShhLGQYc4Bv/aceHbmBhOz1XgUnuTZgcxjxk+WXwNyDXavv5QHD1QEFV0FwbTSQtNq6g4ZcV6y0vZakTjswg=="], "@types/bun": ["@types/bun@1.2.9", "", { "dependencies": { "bun-types": "1.2.9" } }, "sha512-epShhLGQYc4Bv/aceHbmBhOz1XgUnuTZgcxjxk+WXwNyDXavv5QHD1QEFV0FwbTSQtNq6g4ZcV6y0vZakTjswg=="],
@ -466,10 +466,6 @@
"@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="],
"@tailwindcss/cli/tailwindcss": ["tailwindcss@4.1.1", "", {}, "sha512-QNbdmeS979Efzim2g/bEvfuh+fTcIdp1y7gA+sb6OYSW74rt7Cr7M78AKdf6HqWT3d5AiTb7SwTT3sLQxr4/qw=="],
"@tailwindcss/node/tailwindcss": ["tailwindcss@4.1.1", "", {}, "sha512-QNbdmeS979Efzim2g/bEvfuh+fTcIdp1y7gA+sb6OYSW74rt7Cr7M78AKdf6HqWT3d5AiTb7SwTT3sLQxr4/qw=="],
"lightningcss/detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="], "lightningcss/detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="],
"promise-make-counter/promise-make-naked": ["promise-make-naked@3.0.2", "", {}, "sha512-B+b+kQ1YrYS7zO7P7bQcoqqMUizP06BOyNSBEnB5VJKDSWo8fsVuDkfSmwdjF0JsRtaNh83so5MMFJ95soH5jg=="], "promise-make-counter/promise-make-naked": ["promise-make-naked@3.0.2", "", {}, "sha512-B+b+kQ1YrYS7zO7P7bQcoqqMUizP06BOyNSBEnB5VJKDSWo8fsVuDkfSmwdjF0JsRtaNh83so5MMFJ95soH5jg=="],

View file

@ -1,3 +1,5 @@
preload = ["./image-plugin.ts"]
[install.scopes] [install.scopes]
"@jsr" = "https://npm.jsr.io" "@jsr" = "https://npm.jsr.io"

29
image-plugin.ts Normal file
View file

@ -0,0 +1,29 @@
import { plugin, type BunPlugin } from "bun";
const imageLoaderPlugin: BunPlugin = {
name: "image-loader",
setup(builder) {
builder.onLoad({ filter: /\.(png|jpg|jpeg|webp)/ }, async ({ path }) => {
try {
const file = Bun.file(path);
const bytes = await file.bytes();
return {
exports: { default: bytes },
loader: "object",
}
} catch (err) {
console.error(err);
if (err instanceof Error) {
throw new Error(`Failed to load file: ${err.message}`);
} else if (typeof err === 'string') {
throw new Error(`Failed to load file: ${err}`);
}
throw new Error("Failed to load file");
}
});
}
};
plugin(imageLoaderPlugin);
export default imageLoaderPlugin;

View file

@ -1,14 +1,14 @@
{ {
"name": "userscripts", "name": "userscripts",
"module": "src/server.ts", "module": "src/index.ts",
"type": "module", "type": "module",
"private": true, "private": true,
"scripts": { "scripts": {
"start": "bun run src/server.ts", "start": "bun run src/index.ts",
"dev": "bun --watch run src/server.ts", "dev": "bun --watch run src/index.ts",
"dev:userscripts": "bun --watch run src/build.ts", "dev:userscripts": "bun --watch run src/build.ts",
"hot": "bun --hot run src/server.ts", "hot": "bun --hot run src/index.ts",
"build": "bun build src/server.ts --compile --minify --sourcemap --target=bun-linux-x64-modern --outfile server", "build": "bun build src/index.ts --compile --minify --sourcemap --target=bun-linux-x64-modern --outfile dist/app",
"build:userscripts": "bun run src/build.ts" "build:userscripts": "bun run src/build.ts"
}, },
"devDependencies": { "devDependencies": {
@ -21,12 +21,12 @@
"prettier-plugin-tailwindcss": "^0.6.11" "prettier-plugin-tailwindcss": "^0.6.11"
}, },
"dependencies": { "dependencies": {
"@tailwindcss/cli": "4.1.1", "@tailwindcss/cli": "4.1.3",
"bun-plugin-svelte": "^0.0.6", "bun-plugin-svelte": "^0.0.6",
"bun-plugin-tailwind": "^0.0.15", "bun-plugin-tailwind": "^0.0.15",
"tailwindcss": "^4.1.3" "tailwindcss": "^4.1.3"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": "^5.8.2" "typescript": "^5.8.3"
} }
} }

0
src/client/.gitkeep Normal file
View file

25
src/images.d.ts vendored Normal file
View file

@ -0,0 +1,25 @@
declare module '*.png' {
const value: Uint8Array<ArrayBufferLike>;
// const file: Bun.BunFile;
// export { file };
export default value;
}
declare module '*.jpeg' {
const value: Uint8Array<ArrayBufferLike>;
// const file: Bun.BunFile;
// export { file };
export default value;
}
declare module '*.jpg' {
const value: Uint8Array<ArrayBufferLike>;
// const file: Bun.BunFile;
// export { file };
export default value;
}
declare module '*.webp' {
const value: Uint8Array<ArrayBufferLike>;
// const file: Bun.BunFile;
// export { file };
export default value;
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,110 @@
import homepage from "@routes/index.html";
import favicon from "@static/favicon.png";
import robotsTxt from "@static/robots.txt";
import sitemapTxt from "@static/sitemap.txt";
import { env } from "bun";
import path from "path";
const development = env.NODE_ENV !== "production";
const faviconInit = { headers: new Headers({ 'Content-Type': 'image/png' }) };
let htmlFiles: Set<string>;
let scriptFiles: Set<string>;
let cssFiles: Set<string>;
const globScanOptions: Bun.GlobScanOptions = {
absolute: true,
};
async function load() {
await Bun.$`bun run src/server/build.ts`;
const tempHtml: Set<string> = new Set();
const userHtml = new Bun.Glob("./build/*.html");
for await (const filePath of userHtml.scan(globScanOptions)) {
tempHtml.add(path.parse(filePath).base);
}
htmlFiles = tempHtml;
const tempScripts: Set<string> = new Set();
const userJs = new Bun.Glob("./build/*.user.js");
for await (const filePath of userJs.scan(globScanOptions)) {
tempScripts.add(path.parse(filePath).base);
}
scriptFiles = tempScripts;
const tempStyles: Set<string> = new Set();
const css = new Bun.Glob("./build/*.user.css");
for await (const filePath of css.scan(globScanOptions)) {
tempStyles.add(path.parse(filePath).base);
}
cssFiles = tempStyles;
}
await load();
Bun.serve({
routes: {
"/": homepage,
"/robots.txt": new Response(robotsTxt, {
headers: { "Content-Type": "text/plain" },
}),
"/sitemap.txt": new Response(sitemapTxt, {
headers: { "Content-Type": "text/plain" },
}),
"/favicon.ico": new Response(favicon, faviconInit),
"/health": new Response("OK"),
"/html/:html": async (req) => {
const html = req.params.html.toLocaleLowerCase();
if (!htmlFiles.has(html)) {
return new Response("Not found", { status: 404 });
}
const file = Bun.file(`./build/${html}`);
return new Response(file, {
headers: { "Content-Type": "text/css" },
});
},
"/scripts/:script": async (req) => {
const script = req.params.script.toLocaleLowerCase();
if (!scriptFiles.has(script)) {
return new Response("Not found", { status: 404 });
}
const file = Bun.file(`./build/${script}`);
return new Response(file, {
headers: { "Content-Type": "application/javascript" },
});
},
"/styles/:style": async (req) => {
const style = req.params.style.toLocaleLowerCase();
if (!cssFiles.has(style)) {
return new Response("Not found", { status: 404 });
}
const file = Bun.file(`./build/${style}`);
return new Response(file, {
headers: { "Content-Type": "text/css" },
});
},
},
development,
// async fetch(req, server) {
// return new Response("Not found", { status: 404 });
// },
});
if (development) {
setInterval(async () => {
try {
await load();
} catch (e) {
console.error(e);
}
}, 2500);
}

108
src/routes/index.html Normal file
View file

@ -0,0 +1,108 @@
<!doctype html>
<html lang="en" class="min-h-dvh">
<head>
<title>Userscripts - skaarup.dev</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="@static/favicon.png" />
<link rel="stylesheet" href="./index.css" />
</head>
<body
class="min-h-dvh bg-gray-950 bg-cover bg-fixed bg-center bg-no-repeat font-mono text-pretty text-gray-100 selection:bg-pink-600 selection:text-gray-200"
>
<a
href="#main-content"
class="absolute top-0 left-0 z-50 rounded-b-sm bg-pink-600 px-1 pt-0.5 text-xs text-gray-100 not-focus:sr-only focus:outline-none"
>
Skip to main content
</a>
<header class="content sticky top-0 z-20 grid bg-gray-950 py-2 font-mono sm:px-2">
<div class="col-[content] grid grid-cols-3">
<div class="flex items-center gap-8"></div>
<div class="flex items-center justify-center">
<a
href="/"
class="block text-center underline decoration-transparent transition-colors hover:decoration-pink-600"
>Userscripts</a>
</div>
<div class="flex items-center justify-end gap-2 py-2 md:gap-4">
<a
class="block"
href="https://git.skaarup.dev/nikiskaarup/userscripts"
target="_blank"
referrerpolicy="no-referrer"
>
<span class="sr-only">git.skaarup.dev/nikiskaarup/userscripts</span>
<svg
class="aspect-square h-8"
width="32"
height="32"
viewBox="0 0 98 96"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z"
fill="#fff"
/>
</svg>
</a>
</div>
</div>
</header>
<main id="main-content">
<article class="content grid">
<header class="col-[content] flex flex-col gap-2 py-8">
<h1 class="text-center text-3xl">Typing..</h1>
</header>
<section class="content bg-neutral col-[content] grid gap-2 py-8">
<h2 class="scroll-m-24 text-2xl" id="userscripts">
<a href="#userscripts"> Userscripts </a>
</h2>
<ul class="flex list-inside list-disc flex-row gap-2">
<li>
<a
href="/scripts/manga-reading.user.js"
class="underline decoration-indigo-500 transition-colors hover:decoration-pink-600"
target="_blank"
referrerpolicy="no-referrer"
>Manga Reading</a
>
-
<a
href="https://git.skaarup.dev/nikiskaarup/userscripts"
class="underline decoration-indigo-500 transition-colors hover:decoration-pink-600"
target="_blank"
referrerpolicy="no-referrer"
>Repository</a
>
- Adds keyboard navigation to manganato like sites, and
<a
href="https://git.skaarup.dev/nikiskaarup/progress-tracker-api-v2"
class="underline decoration-indigo-500 transition-colors hover:decoration-pink-600"
target="_blank"
referrerpolicy="no-referrer"
>progress</a
>
<a
href="https://git.skaarup.dev/nikiskaarup/progress-tracker-v3"
class="underline decoration-indigo-500 transition-colors hover:decoration-pink-600"
target="_blank"
referrerpolicy="no-referrer"
>tracking</a
>
updated via hotkeys
</li>
</ul>
</section>
</article>
</main>
</body>
</html>

View file

@ -1,113 +0,0 @@
import { env } from "bun";
import homepage from "./index.html";
import robotsTxt from "./static/robots.txt";
import sitemapTxt from "./static/sitemap.txt";
// @ts-ignore ts2307
import icon from "./static/favicon.png" with { type: "file" };
import path from "path";
const favicon = await Bun.file(icon).bytes();
let htmlFiles: Set<string>;
let scriptFiles: Set<string>;
let cssFiles: Set<string>;
const development = env.NODE_ENV !== "production";
const globScanOptions: Bun.GlobScanOptions = {
absolute: true,
};
async function load() {
await Bun.$`bun run src/build.ts`;
const tempHtml: Set<string> = new Set();
const userHtml = new Bun.Glob("./build/*.html");
for await (const filePath of userHtml.scan(globScanOptions)) {
tempHtml.add(path.parse(filePath).base);
}
htmlFiles = tempHtml;
const tempScripts: Set<string> = new Set();
const userJs = new Bun.Glob("./build/*.user.js");
for await (const filePath of userJs.scan(globScanOptions)) {
tempScripts.add(path.parse(filePath).base);
}
scriptFiles = tempScripts;
const tempStyles: Set<string> = new Set();
const css = new Bun.Glob("./build/*.user.css");
for await (const filePath of css.scan(globScanOptions)) {
tempStyles.add(path.parse(filePath).base);
}
cssFiles = tempStyles;
}
await load();
Bun.serve({
routes: {
"/": homepage,
"/robots.txt": new Response(robotsTxt, {
headers: { "Content-Type": "text/plain" },
}),
"/sitemap.txt": new Response(sitemapTxt, {
headers: { "Content-Type": "text/plain" },
}),
"/favicon.ico": new Response(favicon, {
headers: { "Content-Type": "image/png" },
}),
"/health": new Response("OK"),
"/html/:html": async (req) => {
const html = req.params.html.toLocaleLowerCase();
if (!htmlFiles.has(html)) {
return new Response("Not found", { status: 404 });
}
const file = Bun.file(`./build/${html}`);
return new Response(file, {
headers: { "Content-Type": "text/css" },
});
},
"/scripts/:script": async (req) => {
const script = req.params.script.toLocaleLowerCase();
if (!scriptFiles.has(script)) {
return new Response("Not found", { status: 404 });
}
const file = Bun.file(`./build/${script}`);
return new Response(file, {
headers: { "Content-Type": "application/javascript" },
});
},
"/styles/:style": async (req) => {
const style = req.params.style.toLocaleLowerCase();
if (!cssFiles.has(style)) {
return new Response("Not found", { status: 404 });
}
const file = Bun.file(`./build/${style}`);
return new Response(file, {
headers: { "Content-Type": "text/css" },
});
},
},
development,
// async fetch(req, server) {
// return new Response("Not found", { status: 404 });
// },
});
if (development) {
setInterval(async () => {
try {
await load();
} catch (e) {
console.error(e);
}
}, 2500);
}

0
src/server/.gitkeep Normal file
View file

View file

@ -26,7 +26,7 @@ const globScanOptions: Bun.GlobScanOptions = {
absolute: true, absolute: true,
}; };
const userscripts = new Bun.Glob("./src/userscripts/*/*.user.ts"); const userscripts = new Bun.Glob("./src/server/userscripts/*/*.user.ts");
for await (const absPath of userscripts.scan(globScanOptions)) { for await (const absPath of userscripts.scan(globScanOptions)) {
const parsed = path.parse(absPath); const parsed = path.parse(absPath);
console.log(`Building ${parsed.base}...`); console.log(`Building ${parsed.base}...`);
@ -63,7 +63,7 @@ for await (const absPath of userscripts.scan(globScanOptions)) {
await swapHtmlImports(fileText, `./build/${parsed.name}.js`); await swapHtmlImports(fileText, `./build/${parsed.name}.js`);
} }
const styles = new Bun.Glob("./src/userscripts/*/*.user.css"); const styles = new Bun.Glob("./src/server/userscripts/*/*.user.css");
for await (const absPath of styles.scan(globScanOptions)) { for await (const absPath of styles.scan(globScanOptions)) {
const name = path.parse(absPath).base; const name = path.parse(absPath).base;

File diff suppressed because one or more lines are too long

View file

@ -3,7 +3,7 @@
// Environment setup & latest features // Environment setup & latest features
"lib": [ "lib": [
"ESNext", "ESNext",
"DOM" "DOM",
], ],
"target": "ESNext", "target": "ESNext",
"module": "ESNext", "module": "ESNext",
@ -23,6 +23,23 @@
// Some stricter flags (disabled by default) // Some stricter flags (disabled by default)
"noUnusedLocals": false, "noUnusedLocals": false,
"noUnusedParameters": false, "noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false "noPropertyAccessFromIndexSignature": false,
} "paths": {
"@client/*": [
"./src/client/*"
],
"@server/*": [
"./src/server/*"
],
"@routes/*": [
"./src/routes/*"
],
"@static/*": [
"./src/static/*"
],
}
},
"exclude": [
"node_modules"
]
} }