feat: improve path handling in pathFromUri and toEntryInfo functions for better display name resolution
This commit is contained in:
parent
ed302d7156
commit
d1270bc604
|
|
@ -102,34 +102,47 @@ export interface EntryInfo {
|
||||||
* path-relative work everywhere else.
|
* path-relative work everywhere else.
|
||||||
*/
|
*/
|
||||||
function pathFromUri(uri: string, baseUrl: string): string {
|
function pathFromUri(uri: string, baseUrl: string): string {
|
||||||
|
let p: string;
|
||||||
try {
|
try {
|
||||||
// Absolute URL → take just the pathname.
|
// Absolute URL → take just the pathname.
|
||||||
if (/^https?:\/\//i.test(uri)) {
|
if (/^https?:\/\//i.test(uri)) {
|
||||||
const u = new URL(uri);
|
const u = new URL(uri);
|
||||||
return normalizePath(decodeURIComponent(u.pathname));
|
p = u.pathname;
|
||||||
|
} else {
|
||||||
|
p = uri;
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
/* ignore */
|
p = uri;
|
||||||
}
|
}
|
||||||
// Already-relative URI: strip a host prefix if the server added one,
|
// Strip a host prefix if the server added one (e.g. lighttpd).
|
||||||
// then ensure a leading `/`.
|
|
||||||
let p = uri;
|
|
||||||
try {
|
try {
|
||||||
const host = new URL(baseUrl).hostname;
|
const host = new URL(baseUrl).hostname;
|
||||||
if (p.startsWith('/' + host + '/')) p = p.slice(host.length + 1);
|
if (p.startsWith('/' + host + '/')) p = p.slice(host.length + 1);
|
||||||
} catch {
|
} catch {
|
||||||
/* ignore */
|
/* ignore */
|
||||||
}
|
}
|
||||||
|
// Always URL-decode so the rest of the app sees literal characters
|
||||||
|
// (e.g. spaces) instead of %20 in names and paths.
|
||||||
|
try {
|
||||||
|
p = decodeURIComponent(p);
|
||||||
|
} catch {
|
||||||
|
/* leave as-is on malformed encoding */
|
||||||
|
}
|
||||||
return normalizePath(p);
|
return normalizePath(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
function toEntryInfo(e: WebDAVEntry, baseUrl: string): EntryInfo {
|
function toEntryInfo(e: WebDAVEntry, baseUrl: string): EntryInfo {
|
||||||
const rawPath = e.path && e.path.length > 0 ? e.path : e.uri;
|
const rawPath = e.path && e.path.length > 0 ? e.path : e.uri;
|
||||||
const fullPath = pathFromUri(rawPath, baseUrl);
|
const fullPath = pathFromUri(rawPath, baseUrl);
|
||||||
// Some servers (notably webdav3.py) report the full path as the
|
// Prefer the server-provided displayname when it looks like a leaf
|
||||||
// <displayname> for collections. Always use the leaf of the resolved
|
// (no slashes). Some servers (notably older webdav3.py) used to
|
||||||
// path so the UI shows a name, not a path.
|
// return the full path as the displayname; in that case fall back to
|
||||||
const name = basename(fullPath) || e.name;
|
// the leaf of the resolved path.
|
||||||
|
const looksLikePath = (s: string) => s.includes('/');
|
||||||
|
const name =
|
||||||
|
(e.name && !looksLikePath(e.name) ? e.name : '') ||
|
||||||
|
basename(fullPath) ||
|
||||||
|
e.name;
|
||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
path: fullPath,
|
path: fullPath,
|
||||||
|
|
@ -149,11 +162,18 @@ export async function listDirectory(path: string): Promise<EntryInfo[]> {
|
||||||
// The manager's `open` requires an absolute URL on the configured server.
|
// The manager's `open` requires an absolute URL on the configured server.
|
||||||
const collectionUrl = pathToUrl(normalizePath(path), base);
|
const collectionUrl = pathToUrl(normalizePath(path), base);
|
||||||
const listing = await manager.open(collectionUrl);
|
const listing = await manager.open(collectionUrl);
|
||||||
|
const selfPath = normalizePath(path);
|
||||||
const entries: EntryInfo[] = [];
|
const entries: EntryInfo[] = [];
|
||||||
for (const e of Object.values(listing)) {
|
for (const e of Object.values(listing)) {
|
||||||
if (e && e.name) {
|
if (!e || !e.name) continue;
|
||||||
entries.push(toEntryInfo(e, base));
|
const info = toEntryInfo(e, base);
|
||||||
}
|
// Filter out the listing root itself (it appears as an entry whose
|
||||||
|
// path equals the requested collection) and any entries whose path
|
||||||
|
// doesn't sit directly under the requested collection.
|
||||||
|
if (info.path === selfPath) continue;
|
||||||
|
const parent = splitPath(info.path).parent;
|
||||||
|
if (parent !== selfPath) continue;
|
||||||
|
entries.push(info);
|
||||||
}
|
}
|
||||||
// Folders first, then alpha (case-insensitive).
|
// Folders first, then alpha (case-insensitive).
|
||||||
entries.sort((a, b) => {
|
entries.sort((a, b) => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user