mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-10-28 19:35:27 +08:00
57 lines
1.7 KiB
JavaScript
57 lines
1.7 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import { access, readdir, rename } from "node:fs/promises";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
|
|
function decodePathSegment(segment) {
|
|
const decoded = decodeURIComponent(segment);
|
|
if (decoded.includes("/") || decoded.includes("\\") || decoded.includes("\0")) {
|
|
throw new Error(`Refusing to decode unsafe output path segment: ${segment}`);
|
|
}
|
|
return decoded;
|
|
}
|
|
|
|
async function exists(target) {
|
|
try {
|
|
await access(target);
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export async function normalizeStaticPaths(directory) {
|
|
let renamed = 0;
|
|
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
const source = path.join(directory, entry.name);
|
|
if (entry.isDirectory()) renamed += await normalizeStaticPaths(source);
|
|
|
|
const decodedName = decodePathSegment(entry.name);
|
|
if (decodedName === entry.name) continue;
|
|
|
|
const destination = path.join(directory, decodedName);
|
|
if (await exists(destination)) {
|
|
throw new Error(`Static output path collision: ${source} -> ${destination}`);
|
|
}
|
|
await rename(source, destination);
|
|
renamed += 1;
|
|
}
|
|
return renamed;
|
|
}
|
|
|
|
async function main() {
|
|
const publicRoot = path.join(ROOT, "dist/public");
|
|
const renamed = await normalizeStaticPaths(publicRoot);
|
|
console.log(`Normalized ${renamed} percent-encoded static path segments`);
|
|
}
|
|
|
|
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
main().catch((error) => {
|
|
console.error(error.stack || error.message);
|
|
process.exitCode = 1;
|
|
});
|
|
}
|