extremely wip tangled spa
1export interface TreeNode { 2 name: string; 3 fullPath: string; 4 type: "file" | "directory"; 5 children?: TreeNode[]; 6} 7 8type BuildNode = { 9 children: { [key: string]: BuildNode }; 10}; 11 12export function buildTree(paths: string[]): TreeNode { 13 // sorry i used claude for this 14 const root: { [key: string]: BuildNode } = {}; 15 16 for (const path of paths) { 17 const parts = path.split("/"); 18 let current = root; 19 20 for (let i = 0; i < parts.length; i++) { 21 const part = parts[i]; 22 current[part] ??= { children: {} }; 23 if (i < parts.length - 1) { 24 current = current[part].children; 25 } 26 } 27 } 28 29 const entries = (obj: BuildNode["children"], path: string) => 30 Object.entries(obj) 31 .map(([k, v]) => convert(path, v, k)) 32 .sort((a, b) => { 33 if (a.type !== b.type) return a.type === "directory" ? -1 : 1; 34 35 const aDot = a.name.startsWith("."); 36 const bDot = b.name.startsWith("."); 37 if (aDot !== bDot) return aDot ? -1 : 1; 38 39 return a.name.localeCompare(b.name, undefined, { numeric: true }); 40 }); 41 42 const convert = (path: string, node: BuildNode, name: string): TreeNode => { 43 const hasChildren = Object.keys(node.children).length > 0; 44 const fullPath = `${path}${name}`; 45 return { 46 name, 47 type: hasChildren ? "directory" : "file", 48 fullPath, 49 children: hasChildren 50 ? entries(node.children, `${fullPath}/`) 51 : undefined, 52 }; 53 }; 54 55 return { 56 name: "", 57 fullPath: "", 58 type: "directory", 59 children: entries(root, ""), 60 }; 61}