feat: add mapix logo assets

This commit is contained in:
br0tkasten committed 2026-06-13 08:46:37 +02:00
1 parent 5e10be463e
commit 4dd9e5e487
6 files changed
+135 -7

No files matched your search

+20 -5
View File
@@ -3,24 +3,31 @@ import type { ServerResponse } from "node:http";
const CLIENT_ASSET_PREFIX = "/client/";
const VENDOR_ASSET_PREFIX = "/vendor/";
const APP_ASSET_PREFIX = "/assets/";
export function isClientAssetPath(pathname: string): boolean {
return pathname.startsWith(CLIENT_ASSET_PREFIX) || pathname.startsWith(VENDOR_ASSET_PREFIX);
return (
pathname.startsWith(CLIENT_ASSET_PREFIX) ||
pathname.startsWith(VENDOR_ASSET_PREFIX) ||
pathname.startsWith(APP_ASSET_PREFIX)
);
}
export async function handleClientAssetRequest(url: URL, res: ServerResponse): Promise<void> {
const isVendorAsset = url.pathname.startsWith(VENDOR_ASSET_PREFIX);
const assetPrefix = isVendorAsset ? VENDOR_ASSET_PREFIX : CLIENT_ASSET_PREFIX;
const isAppAsset = url.pathname.startsWith(APP_ASSET_PREFIX);
const assetPrefix = isVendorAsset ? VENDOR_ASSET_PREFIX : isAppAsset ? APP_ASSET_PREFIX : CLIENT_ASSET_PREFIX;
const assetName = url.pathname.slice(assetPrefix.length);
if (!isAllowedAssetPath(assetName, isVendorAsset)) {
if (!isAllowedAssetPath(assetName, isVendorAsset, isAppAsset)) {
res.statusCode = 404;
res.end("Not found");
return;
}
try {
const assetUrl = new URL(`../${isVendorAsset ? "vendor" : "client"}/${assetName}`, import.meta.url);
const assetDirectory = isVendorAsset ? "vendor" : isAppAsset ? "assets" : "client";
const assetUrl = new URL(`../${assetDirectory}/${assetName}`, import.meta.url);
const source = await readFile(assetUrl);
res.statusCode = 200;
res.setHeader("content-type", getContentType(assetName));
@@ -32,11 +39,15 @@ export async function handleClientAssetRequest(url: URL, res: ServerResponse): P
}
}
function isAllowedAssetPath(assetName: string, isVendorAsset: boolean): boolean {
function isAllowedAssetPath(assetName: string, isVendorAsset: boolean, isAppAsset: boolean): boolean {
if (assetName.split("/").includes("..")) {
return false;
}
if (isAppAsset) {
return /^[a-z0-9_.-]+\.svg$/i.test(assetName);
}
if (isVendorAsset) {
return /^[a-z0-9/_.-]+\.(css|js|mjs|png)$/i.test(assetName);
}
@@ -53,5 +64,9 @@ function getContentType(assetName: string): string {
return "image/png";
}
if (assetName.endsWith(".svg")) {
return "image/svg+xml; charset=utf-8";
}
return "text/javascript; charset=utf-8";
}
+1
View File
@@ -7,6 +7,7 @@ export function htmlPage(): string {
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>mapix</title>
<link rel="icon" type="image/svg+xml" href="/assets/favicon.svg" />
<link rel="stylesheet" href="/vendor/leaflet/leaflet.css" />
<style>
${APP_STYLES}