/** * URL helpers. Pure functions, no DOM access. */ /** * If `url` is not absolute, resolve it against `base`. Otherwise returns `url`. * Always returns a string ending in a way that matches the input (i.e. trailing * slashes are preserved for collection URLs). */ export function normalizeURL(url, base) { if (!/^https?:\/\//.test(url)) { const baseWithSlash = base.endsWith('/') ? base : base + '/'; return new URL(url, baseWithSlash).href; } return url; } /** * Join a path onto a base URL, ensuring exactly one `/` between them. * Trailing slashes on `base` are preserved. */ export function joinURL(base, path) { const baseWithSlash = base.endsWith('/') ? base : base + '/'; return new URL(path, baseWithSlash).href; } /** Return everything before the last `/` in `path`. */ export function dirname(path) { const idx = path.lastIndexOf('/'); return idx === -1 ? '' : path.slice(0, idx); } /** Return everything after the last `/` in `path`. */ export function basename(path) { const idx = path.lastIndexOf('/'); return idx === -1 ? path : path.slice(idx + 1); } /** * Resolve a parent URL of a collection URL. Strips the trailing slash * (the collection marker), pops the directory's own name, then re-appends * the trailing slash. * * @example * parentCollectionURL("https://x/webdav/Music/Albums/") // "https://x/webdav/Music/" * parentCollectionURL("https://x/webdav/") // "https://x/" */ export function parentCollectionURL(uri) { const trimmed = uri.replace(/\/+$/, ''); const parent = dirname(trimmed); return parent ? parent + '/' : ''; } /** * Strip a leading host prefix from a name (e.g. "example.comFoo" → "Foo"). * Used to remove the WebDAV server's hostname from filenames that some servers * include as a prefix on each entry. */ export function stripHostPrefix(name, host) { if (!name || !host) { return name; } if (name.startsWith(host)) { const stripped = name.slice(host.length); return stripped.length ? stripped : host; } return name; }