packagetreeimport("os""path""path/filepath""sort""static-repo/internal/models""static-repo/internal/utils""strings")funcBuildFileTree(root,currentRel,urlPrefixstring)(*models.FileNode,error){absPath:=filepath.Join(root,currentRel)entries,err:=os.ReadDir(absPath)iferr!=nil{returnnil,err}node:=&models.FileNode{Name:filepath.Base(absPath),Path:currentRel,IsDir:true,}ifcurrentRel==""{node.Name="Root"}for_,entry:=rangeentries{rel:=filepath.Join(currentRel,entry.Name())ifentry.IsDir(){child,err:=BuildFileTree(root,rel,urlPrefix)iferr!=nil{returnnil,err}node.Children=append(node.Children,child)}else{ctype:=utils.GetContentType(entry.Name())linkName:=relifstrings.ToLower(filepath.Base(rel))=="readme.md"{linkName=filepath.Join(filepath.Dir(rel),"index")}link:=path.Join("/",urlPrefix,filepath.ToSlash(linkName))+".html"node.Children=append(node.Children,&models.FileNode{Name:entry.Name(),Path:filepath.ToSlash(rel),Link:link,IsDir:false,ContentType:ctype,Icon:utils.GetIconClass(ctype),})}}sort.Slice(node.Children,func(i,jint)bool{a,b:=node.Children[i],node.Children[j]// 1. Folders firstifa.IsDir!=b.IsDir{returna.IsDir}// Both are folders OR both are filesif!a.IsDir{// both are filesisAMd:=strings.HasSuffix(strings.ToLower(a.Name),".md")isBMd:=strings.HasSuffix(strings.ToLower(b.Name),".md")ifisAMd!=isBMd{returnisAMd}ifisAMd&&isBMd{isAReadme:=strings.ToLower(a.Name)=="readme.md"isBReadme:=strings.ToLower(b.Name)=="readme.md"ifisAReadme!=isBReadme{returnisAReadme}}}// Alphabetical within groups (folders, markdown, or other files)returnstrings.ToLower(a.Name)<strings.ToLower(b.Name)})returnnode,nil}