Skip to content

Commit 0a28b8e

Browse files
author
Sandi Karajic
committed
fix parent directory
1 parent 4431b65 commit 0a28b8e

2 files changed

Lines changed: 63 additions & 42 deletions

File tree

src/lib/nginx-index.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export const parseTemplate = (): FileIndex => {
8686
const sizeCell = row.querySelector('td.size');
8787
const dateCell = row.querySelector('td.date');
8888

89-
const name = linkCell?.textContent?.trim() || '';
89+
let name = linkCell?.textContent?.trim() || '';
9090
const link = linkCell?.getAttribute('href') || '';
9191
const sizeRaw = sizeCell?.textContent?.trim() || '-';
9292
const dateRaw = dateCell?.textContent?.trim() || '';
@@ -95,8 +95,13 @@ export const parseTemplate = (): FileIndex => {
9595
const size = parseSize(sizeRaw);
9696
const date = parseDate(dateRaw);
9797

98+
// Identify parent directory by its href and set name to ".."
99+
if (link === '../') {
100+
name = '..';
101+
}
102+
98103
return { name, link, size, date, isDirectory };
99104
});
100105

101106
return { path, files };
102-
}
107+
};

src/lib/utils.ts

Lines changed: 56 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export function getFileIcon(fileName: string, isDirectory: boolean) {
7979
}
8080

8181
/**
82-
* Sorts an array of FileEntry.
82+
* Sorts an array of FileEntry, always keeping the parent directory ("../") at the top.
8383
* If no column is provided, sorts directories first, then files, each group by name using natural order.
8484
* If a column is provided, sorts by that column (respecting direction), ignoring directory/file type.
8585
*
@@ -95,53 +95,69 @@ export function sortFiles(
9595
): FileEntry[] {
9696
const sorted = [...files];
9797

98-
// Default sort: directories first, then files, both sorted by name (natural, case‑insensitive)
98+
// Helper to wrap a comparator and always put the parent directory first
99+
const withParentPriority = (compareFn: (a: FileEntry, b: FileEntry) => number) => {
100+
return (a: FileEntry, b: FileEntry): number => {
101+
const aIsParent = a.link === '../';
102+
const bIsParent = b.link === '../';
103+
104+
if (aIsParent && !bIsParent) return -1; // parent comes first
105+
if (!aIsParent && bIsParent) return 1; // parent comes first
106+
if (aIsParent && bIsParent) return 0; // both parent (shouldn't happen)
107+
108+
// Normal comparison
109+
return compareFn(a, b);
110+
};
111+
};
112+
113+
// Default sort: directories first, then name natural order
99114
if (column == null) {
100-
return sorted.sort((a, b) => {
101-
// Directories first
102-
if (a.isDirectory !== b.isDirectory) {
103-
return a.isDirectory ? -1 : 1;
104-
}
105-
// Same type → natural sort by name
106-
return naturalCompare(a.name, b.name);
107-
});
115+
return sorted.sort(
116+
withParentPriority((a, b) => {
117+
if (a.isDirectory !== b.isDirectory) {
118+
return a.isDirectory ? -1 : 1;
119+
}
120+
return naturalCompare(a.name, b.name);
121+
})
122+
);
108123
}
109124

110125
// Column‑based sort – direction defaults to 'asc'
111126
const dir = direction ?? 'asc';
112127
const multiplier = dir === 'asc' ? 1 : -1;
113128

114-
return sorted.sort((a, b) => {
115-
let cmp = 0;
116-
117-
switch (column) {
118-
case 'name':
119-
cmp = naturalCompare(a.name, b.name);
120-
break;
121-
122-
case 'size':
123-
// Nulls always last
124-
if (a.size === null && b.size === null) cmp = 0;
125-
else if (a.size === null) cmp = 1; // a is null → a after b
126-
else if (b.size === null) cmp = -1; // b is null → a before b
127-
else cmp = a.size.bytes - b.size.bytes;
128-
break;
129-
130-
case 'date':
131-
if (a.date === null && b.date === null) cmp = 0;
132-
else if (a.date === null) cmp = 1;
133-
else if (b.date === null) cmp = -1;
134-
else cmp = a.date.getTime() - b.date.getTime();
135-
break;
136-
137-
default:
138-
// Exhaustiveness check
139-
const _: never = column;
140-
return 0;
141-
}
129+
return sorted.sort(
130+
withParentPriority((a, b) => {
131+
let cmp = 0;
132+
133+
switch (column) {
134+
case 'name':
135+
cmp = naturalCompare(a.name, b.name);
136+
break;
137+
138+
case 'size':
139+
if (a.size === null && b.size === null) cmp = 0;
140+
else if (a.size === null) cmp = 1; // nulls last
141+
else if (b.size === null) cmp = -1;
142+
else cmp = a.size.bytes - b.size.bytes;
143+
break;
144+
145+
case 'date':
146+
if (a.date === null && b.date === null) cmp = 0;
147+
else if (a.date === null) cmp = 1;
148+
else if (b.date === null) cmp = -1;
149+
else cmp = a.date.getTime() - b.date.getTime();
150+
break;
151+
152+
default:
153+
// Exhaustiveness check
154+
const _: never = column;
155+
return 0;
156+
}
142157

143-
return cmp * multiplier;
144-
});
158+
return cmp * multiplier;
159+
})
160+
);
145161
}
146162

147163
/**

0 commit comments

Comments
 (0)