import { isWindows } from "./os"; /** * Normalize user-provided executable path for the current OS. * - Expands ~ on macOS/Linux via PathUtils (when available) * - Ensures .exe suffix on Windows when missing */ export function normalizeExecutablePath(input: string): string { const trimmed = (input || "").trim(); if (!trimmed) return ""; const path = trimmed; if (isWindows() && !/\.(exe|cmd|bat)$/i.test(path)) { return `${path}.exe`; } return path; } /** Join path segments using Zotero PathUtils (cross-platform). */ export function joinPath(...parts: string[]): string { const filtered = parts.filter(Boolean); if (!filtered.length) return ""; try { return PathUtils.join(...filtered); } catch (e) { ztoolkit.log("[ChatPapers] PathUtils.join failed", filtered, e); throw e; } } /** Normalize user-provided storage directory paths (prefs). */ export function normalizeStoragePath(input: string): string { const trimmed = (input || "").trim(); if (!trimmed) return ""; const unified = trimmed.replace(/\\/g, "/").replace(/\/+/g, "/"); const winMatch = unified.match(/^([A-Za-z]:)(\/.*)?$/); if (winMatch) { const drive = winMatch[1]; const rest = (winMatch[2] || "") .split("/") .filter((part) => part && part !== ".") .join("\\"); return rest ? `${drive}\\${rest}` : drive; } const absolute = unified.startsWith("/"); const parts = unified.split("/").filter((part) => part && part !== "."); let result = parts.join("/"); if (absolute) result = `/${result}`; return result.replace(/\/+$/, "") || (absolute ? "/" : ""); } /** Safe single path segment for file or directory names (cross-platform). */ export function sanitizePathSegment(input: string, maxLen = 120): string { const cleaned = String(input || "") .replace(/[<>:"/\\|?*\x00-\x1f]/g, "_") .replace(/[.\s]+$/, "") .trim(); if (!cleaned) return "_"; if (cleaned.length <= maxLen) return cleaned; let hash = 0; for (let i = 0; i < input.length; i++) { hash = (hash * 31 + input.charCodeAt(i)) | 0; } const tail = Math.abs(hash).toString(36); return `${cleaned.slice(0, Math.max(1, maxLen - tail.length - 1))}_${tail}`; } /** Convert local file path to file:// URL for