@@ -189,7 +189,233 @@ export const generateStructure = (tree: TreeItem[]): DirectoryMap => {
189
189
return structureMap
190
190
}
191
191
192
- export const buildStructureString = ( map : DirectoryMap , prefix = "" , options : TreeCustomizationOptions ) : string => {
192
+ // Get description for files and directories
193
+ const getDescription = ( name : string , isDirectory : boolean , path ?: string ) : string => {
194
+ if ( isDirectory ) {
195
+ return getDirectoryDescription ( name , path || "" )
196
+ } else {
197
+ return getFileDescription ( name )
198
+ }
199
+ }
200
+
201
+ // Directory descriptions based on common patterns
202
+ const getDirectoryDescription = ( dirName : string , fullPath : string ) : string => {
203
+ const lowerName = dirName . toLowerCase ( )
204
+ const lowerPath = fullPath . toLowerCase ( )
205
+
206
+ // Common directory patterns
207
+ const directoryDescriptions : { [ key : string ] : string } = {
208
+ // Build/Config directories
209
+ ".github" : "GitHub workflows and templates" ,
210
+ ".vscode" : "VS Code workspace settings" ,
211
+ ".next" : "Next.js build output" ,
212
+ "dist" : "Distribution/build files" ,
213
+ "build" : "Compiled application files" ,
214
+ "out" : "Output directory" ,
215
+ "public" : "Static assets and public files" ,
216
+ "static" : "Static assets" ,
217
+ "assets" : "Project assets and resources" ,
218
+
219
+ // Source directories
220
+ "src" : "Source code" ,
221
+ "app" : "Application pages and routing" ,
222
+ "pages" : "Application pages" ,
223
+ "components" : "React components" ,
224
+ "lib" : "Utility functions and libraries" ,
225
+ "utils" : "Utility functions" ,
226
+ "helpers" : "Helper functions" ,
227
+ "hooks" : "Custom React hooks" ,
228
+ "context" : "React context providers" ,
229
+ "store" : "State management" ,
230
+ "styles" : "CSS and styling files" ,
231
+ "css" : "Stylesheets" ,
232
+ "scss" : "Sass stylesheets" ,
233
+ "images" : "Image assets" ,
234
+ "fonts" : "Font files" ,
235
+ "icons" : "Icon assets" ,
236
+
237
+ // API and backend
238
+ "api" : "API routes and endpoints" ,
239
+ "server" : "Server-side code" ,
240
+ "backend" : "Backend application code" ,
241
+ "routes" : "Application routes" ,
242
+ "controllers" : "Route controllers" ,
243
+ "models" : "Data models" ,
244
+ "middleware" : "Express middleware" ,
245
+ "database" : "Database files and migrations" ,
246
+ "migrations" : "Database migrations" ,
247
+ "seeds" : "Database seed files" ,
248
+
249
+ // Testing
250
+ "test" : "Test files" ,
251
+ "tests" : "Test files" ,
252
+ "__tests__" : "Jest test files" ,
253
+ "spec" : "Test specifications" ,
254
+ "e2e" : "End-to-end tests" ,
255
+ "cypress" : "Cypress test files" ,
256
+
257
+ // Documentation
258
+ "docs" : "Documentation files" ,
259
+ "documentation" : "Project documentation" ,
260
+
261
+ // Configuration
262
+ "config" : "Configuration files" ,
263
+ "configs" : "Configuration files" ,
264
+
265
+ // Dependencies
266
+ "node_modules" : "NPM dependencies" ,
267
+ "vendor" : "Third-party libraries" ,
268
+
269
+ // UI specific
270
+ "ui" : "UI components" ,
271
+ "layout" : "Layout components" ,
272
+ "layouts" : "Page layouts" ,
273
+ "templates" : "Component templates" ,
274
+
275
+ // Types
276
+ "types" : "TypeScript type definitions" ,
277
+ "@types" : "TypeScript declarations" ,
278
+
279
+ // Workflows
280
+ "workflows" : "CI/CD workflow files"
281
+ }
282
+
283
+ // Check exact matches first
284
+ if ( directoryDescriptions [ lowerName ] ) {
285
+ return directoryDescriptions [ lowerName ]
286
+ }
287
+
288
+ // Check for patterns in the full path
289
+ if ( lowerPath . includes ( "workflow" ) || lowerPath . includes ( ".github" ) ) {
290
+ return "CI/CD workflows"
291
+ }
292
+ if ( lowerPath . includes ( "component" ) ) {
293
+ return "Component files"
294
+ }
295
+ if ( lowerPath . includes ( "page" ) ) {
296
+ return "Page components"
297
+ }
298
+ if ( lowerPath . includes ( "api" ) ) {
299
+ return "API endpoints"
300
+ }
301
+
302
+ return "Directory"
303
+ }
304
+
305
+ // File descriptions based on extensions and names
306
+ const getFileDescription = ( fileName : string ) : string => {
307
+ const lowerName = fileName . toLowerCase ( )
308
+ const extension = fileName . split ( "." ) . pop ( ) ?. toLowerCase ( ) || ""
309
+
310
+ // Specific file names
311
+ const specificFiles : { [ key : string ] : string } = {
312
+ "readme.md" : "Project documentation" ,
313
+ "license" : "Project license" ,
314
+ "license.txt" : "Project license" ,
315
+ "license.md" : "Project license" ,
316
+ "changelog.md" : "Version history" ,
317
+ "contributing.md" : "Contribution guidelines" ,
318
+ "package.json" : "NPM package configuration" ,
319
+ "package-lock.json" : "Dependency lock file" ,
320
+ "yarn.lock" : "Yarn dependency lock file" ,
321
+ "tsconfig.json" : "TypeScript configuration" ,
322
+ "next.config.js" : "Next.js configuration" ,
323
+ "next.config.ts" : "Next.js configuration" ,
324
+ "tailwind.config.js" : "Tailwind CSS configuration" ,
325
+ "tailwind.config.ts" : "Tailwind CSS configuration" ,
326
+ "postcss.config.js" : "PostCSS configuration" ,
327
+ "eslint.config.js" : "ESLint configuration" ,
328
+ ".eslintrc.json" : "ESLint rules" ,
329
+ ".gitignore" : "Git ignore rules" ,
330
+ ".env" : "Environment variables" ,
331
+ ".env.example" : "Environment variables template" ,
332
+ ".env.local" : "Local environment variables" ,
333
+ "vercel.json" : "Vercel deployment config" ,
334
+ "dockerfile" : "Docker container config" ,
335
+ "docker-compose.yml" : "Docker compose config" ,
336
+ "makefile" : "Build automation" ,
337
+ "components.json" : "Component configuration" ,
338
+ "prettier.config.js" : "Code formatting rules"
339
+ }
340
+
341
+ // Check specific file names first
342
+ if ( specificFiles [ lowerName ] ) {
343
+ return specificFiles [ lowerName ]
344
+ }
345
+
346
+ // Extension-based descriptions
347
+ const extensionDescriptions : { [ key : string ] : string } = {
348
+ // Web technologies
349
+ "js" : "JavaScript file" ,
350
+ "jsx" : "React component" ,
351
+ "ts" : "TypeScript file" ,
352
+ "tsx" : "React TypeScript component" ,
353
+ "html" : "HTML page" ,
354
+ "css" : "Stylesheet" ,
355
+ "scss" : "Sass stylesheet" ,
356
+ "sass" : "Sass stylesheet" ,
357
+ "less" : "Less stylesheet" ,
358
+
359
+ // Configuration
360
+ "json" : "JSON configuration" ,
361
+ "yaml" : "YAML configuration" ,
362
+ "yml" : "YAML configuration" ,
363
+ "toml" : "TOML configuration" ,
364
+ "xml" : "XML file" ,
365
+
366
+ // Documentation
367
+ "md" : "Markdown documentation" ,
368
+ "txt" : "Text file" ,
369
+ "pdf" : "PDF document" ,
370
+
371
+ // Images
372
+ "png" : "PNG image" ,
373
+ "jpg" : "JPEG image" ,
374
+ "jpeg" : "JPEG image" ,
375
+ "gif" : "GIF image" ,
376
+ "svg" : "SVG vector image" ,
377
+ "webp" : "WebP image" ,
378
+ "ico" : "Icon file" ,
379
+
380
+ // Video/Audio
381
+ "mp4" : "MP4 video" ,
382
+ "webm" : "WebM video" ,
383
+ "avi" : "AVI video" ,
384
+ "mov" : "QuickTime video" ,
385
+ "mp3" : "MP3 audio" ,
386
+ "wav" : "WAV audio" ,
387
+
388
+ // Other programming languages
389
+ "py" : "Python script" ,
390
+ "java" : "Java source file" ,
391
+ "cpp" : "C++ source file" ,
392
+ "c" : "C source file" ,
393
+ "php" : "PHP script" ,
394
+ "rb" : "Ruby script" ,
395
+ "go" : "Go source file" ,
396
+ "rs" : "Rust source file" ,
397
+ "swift" : "Swift source file" ,
398
+ "kt" : "Kotlin source file" ,
399
+
400
+ // Database
401
+ "sql" : "SQL script" ,
402
+ "db" : "Database file" ,
403
+
404
+ // Archives
405
+ "zip" : "ZIP archive" ,
406
+ "tar" : "TAR archive" ,
407
+ "gz" : "Gzip archive" ,
408
+
409
+ // Others
410
+ "sh" : "Shell script" ,
411
+ "bat" : "Batch script" ,
412
+ "ps1" : "PowerShell script"
413
+ }
414
+
415
+ return extensionDescriptions [ extension ] || "File"
416
+ }
417
+
418
+ export const buildStructureString = ( map : DirectoryMap , prefix = "" , options : TreeCustomizationOptions , currentPath = "" ) : string => {
193
419
let result = ""
194
420
195
421
// Add root directory indicator if enabled
@@ -198,20 +424,43 @@ export const buildStructureString = (map: DirectoryMap, prefix = "", options: Tr
198
424
}
199
425
200
426
const entries = Array . from ( map . entries ( ) )
201
- const lastIndex = entries . length - 1
427
+
428
+ // Sort entries: directories first, then files
429
+ // Within each group, sort alphabetically
430
+ const sortedEntries = entries . sort ( ( [ keyA , valueA ] , [ keyB , valueB ] ) => {
431
+ const isDirectoryA = valueA instanceof Map
432
+ const isDirectoryB = valueB instanceof Map
433
+
434
+ // If one is directory and other is file, directory comes first
435
+ if ( isDirectoryA && ! isDirectoryB ) return - 1
436
+ if ( ! isDirectoryA && isDirectoryB ) return 1
437
+
438
+ // If both are same type (both directories or both files), sort alphabetically
439
+ return keyA . localeCompare ( keyB )
440
+ } )
441
+
442
+ const lastIndex = sortedEntries . length - 1
202
443
203
- entries . forEach ( ( [ key , value ] , index ) => {
444
+ sortedEntries . forEach ( ( [ key , value ] , index ) => {
204
445
const isLast = index === lastIndex
205
446
const connector = getConnector ( isLast , options . asciiStyle )
206
447
const childPrefix = getChildPrefix ( isLast , options . asciiStyle )
207
448
const icon = options . useIcons ? getIcon ( value instanceof Map ) : ""
449
+ const isDirectory = value instanceof Map
450
+
451
+ // Build current file/directory path
452
+ const itemPath = currentPath ? `${ currentPath } /${ key } ` : key
208
453
209
454
// Add trailing slash for directories if enabled
210
- const displayName = ( value instanceof Map && options . showTrailingSlash ) ? `${ key } /` : key
455
+ const displayName = ( isDirectory && options . showTrailingSlash ) ? `${ key } /` : key
456
+
457
+ // Get description for this item
458
+ const description = getDescription ( key , isDirectory , itemPath )
459
+ const descriptionText = options . showDescriptions && description ? ` # ${ description } ` : ""
211
460
212
- result += `${ prefix } ${ connector } ${ icon } ${ displayName } \n`
213
- if ( value instanceof Map ) {
214
- result += buildStructureString ( value , `${ prefix } ${ childPrefix } ` , options )
461
+ result += `${ prefix } ${ connector } ${ icon } ${ displayName } ${ descriptionText } \n`
462
+ if ( isDirectory ) {
463
+ result += buildStructureString ( value , `${ prefix } ${ childPrefix } ` , options , itemPath )
215
464
}
216
465
} )
217
466
0 commit comments