const DRIVE_PATH = /^[A-Za-z]:[\\/]/; const URI_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*:/; export function normalizeProjectAssetPath(sourcePath: string): string { if (typeof sourcePath !== "string" || sourcePath.length === 0 || sourcePath.length > 2048) { throw new Error("ASSET_PATH_INVALID"); } if (sourcePath.includes("\0") || sourcePath.includes("\\") || sourcePath.includes("%")) { throw new Error("ASSET_PATH_OUTSIDE_PROJECT"); } let relative = sourcePath.startsWith("//") ? sourcePath.slice(2) : sourcePath; if (relative.startsWith("/") || DRIVE_PATH.test(relative) || URI_SCHEME.test(relative)) { throw new Error("ASSET_PATH_OUTSIDE_PROJECT"); } const segments = relative.split("/"); if (segments.length === 0 || segments.some((segment) => segment.length === 0 || segment === "." || segment === ".." || /[\u0000-\u001f\u007f]/.test(segment))) { throw new Error("ASSET_PATH_OUTSIDE_PROJECT"); } relative = segments.join("/"); if (!relative) throw new Error("ASSET_PATH_INVALID"); return relative; }