11import type { Entry } from "apache-autoindex-parse" ;
2- import { trimTrailingSlash } from "@luxass/utils" ;
2+ import { trimLeadingSlash , trimTrailingSlash } from "@luxass/utils" ;
3+ import { createGlobMatcher } from "@ucdjs-internal/shared" ;
34import { parse } from "apache-autoindex-parse" ;
45
56/**
@@ -20,13 +21,105 @@ import { parse } from "apache-autoindex-parse";
2021 * console.log(entries); // [{ type: 'directory', name: 'UNIDATA', path: '/UNIDATA', ... }]
2122 * ```
2223 */
23- export async function parseUnicodeDirectory ( html : string ) : Promise < Entry [ ] > {
24- const files = parse ( html , "F2" ) ;
25-
26- return files . map ( ( { type, name, path, lastModified } ) => ( {
27- type,
28- name : trimTrailingSlash ( name ) ,
29- path : trimTrailingSlash ( path ) ,
30- lastModified,
31- } ) ) ;
24+ export async function parseUnicodeDirectory ( html : string , basePath = "" ) : Promise < Entry [ ] > {
25+ const files = parse ( html , {
26+ format : "F2" ,
27+ basePath,
28+ } ) ;
29+
30+ return files . map ( ( entry ) => {
31+ entry . name = trimLeadingSlash ( trimTrailingSlash ( entry . name ) ) ;
32+ return entry ;
33+ } ) ;
34+ }
35+
36+ export interface DirectoryFilterOptions {
37+ /**
38+ * A string to filter file/directory names that start with this query (case-insensitive).
39+ */
40+ query ?: string ;
41+
42+ /**
43+ * A glob pattern to filter file/directory names.
44+ */
45+ pattern ?: string ;
46+
47+ /**
48+ * Type of entries to include: "all" (default), "files", or "directories".
49+ */
50+ type ?: string ;
51+
52+ /**
53+ * Field to sort by: "name" (default) or "lastModified".
54+ */
55+ sort ?: string ;
56+
57+ /**
58+ * Sort order: "asc" (default) or "desc".
59+ */
60+ order ?: string ;
61+ }
62+
63+ /**
64+ * Applies filtering and sorting to directory entries based on query parameters.
65+ *
66+ * @param {Entry[] } files - Array of directory entries to filter and sort
67+ * @param {DirectoryFilterOptions } options - Filter and sort options
68+ * @returns {Entry[] } Filtered and sorted array of entries
69+ */
70+ export function applyDirectoryFiltersAndSort (
71+ files : Entry [ ] ,
72+ options : DirectoryFilterOptions ,
73+ ) : Entry [ ] {
74+ let filtered = [ ...files ] ;
75+
76+ // Apply query filter (prefix search, case-insensitive)
77+ if ( options . query ) {
78+ // eslint-disable-next-line no-console
79+ console . info ( `[v1_files]: applying query filter: ${ options . query } ` ) ;
80+ const queryLower = options . query . toLowerCase ( ) ;
81+ filtered = filtered . filter ( ( entry ) => entry . name . toLowerCase ( ) . startsWith ( queryLower ) ) ;
82+ }
83+
84+ // Apply pattern filter if provided
85+ if ( options . pattern ) {
86+ // eslint-disable-next-line no-console
87+ console . info ( `[v1_files]: applying glob pattern filter: ${ options . pattern } ` ) ;
88+ const matcher = createGlobMatcher ( options . pattern ) ;
89+ filtered = filtered . filter ( ( entry ) => matcher ( entry . name ) ) ;
90+ }
91+
92+ // Apply type filter
93+ const type = options . type || "all" ;
94+ if ( type === "files" ) {
95+ filtered = filtered . filter ( ( entry ) => entry . type === "file" ) ;
96+ } else if ( type === "directories" ) {
97+ filtered = filtered . filter ( ( entry ) => entry . type === "directory" ) ;
98+ }
99+
100+ // Apply sorting (directories always first, like Windows File Explorer)
101+ const sort = options . sort || "name" ;
102+ const order = options . order || "asc" ;
103+
104+ filtered = filtered . toSorted ( ( a , b ) => {
105+ // Directories always come first
106+ if ( a . type !== b . type ) {
107+ return a . type === "directory" ? - 1 : 1 ;
108+ }
109+
110+ // Within same type, apply the requested sort
111+ let comparison : number ;
112+
113+ if ( sort === "lastModified" ) {
114+ // lastModified is always available from parseUnicodeDirectory
115+ comparison = ( a . lastModified ?? 0 ) - ( b . lastModified ?? 0 ) ;
116+ } else {
117+ // Natural name sorting (numeric aware) so 2.0.0 < 10.0.0
118+ comparison = a . name . localeCompare ( b . name , undefined , { numeric : true , sensitivity : "base" } ) ;
119+ }
120+
121+ return order === "desc" ? - comparison : comparison ;
122+ } ) ;
123+
124+ return filtered ;
32125}
0 commit comments