@@ -0,0 +1,174 @@
|
||||
import type { FileNode } from "../types";
|
||||
|
||||
export const addPaths = (node: FileNode, parentPath: string = ""): FileNode => {
|
||||
const currentPath = parentPath ? `${parentPath}/${node.name}` : node.name;
|
||||
const newNode = { ...node, path: currentPath };
|
||||
if (newNode.children) {
|
||||
newNode.children = newNode.children.map((child) =>
|
||||
addPaths(child, currentPath),
|
||||
);
|
||||
}
|
||||
return newNode;
|
||||
};
|
||||
|
||||
export const getAllFolderPaths = (node: FileNode): string[] => {
|
||||
let paths: string[] = [];
|
||||
if (node.type === "folder") {
|
||||
paths.push(node.path || node.name);
|
||||
if (node.children) {
|
||||
node.children.forEach((child) => {
|
||||
paths = [...paths, ...getAllFolderPaths(child)];
|
||||
});
|
||||
}
|
||||
}
|
||||
return paths;
|
||||
};
|
||||
|
||||
export const findNode = (node: FileNode, path: string): FileNode | null => {
|
||||
if (node.path === path) return node;
|
||||
if (node.children) {
|
||||
for (const child of node.children) {
|
||||
const found = findNode(child, path);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const deleteNode = (node: FileNode, path: string): FileNode | null => {
|
||||
if (node.path === path) return null;
|
||||
|
||||
if (node.children) {
|
||||
const filtered = node.children.filter((child) => child.path !== path);
|
||||
const mapped = filtered
|
||||
.map((child) => deleteNode(child, path))
|
||||
.filter((child): child is FileNode => child !== null);
|
||||
return { ...node, children: mapped };
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
export const addNode = (
|
||||
node: FileNode,
|
||||
parentPath: string,
|
||||
newNode: FileNode,
|
||||
): FileNode => {
|
||||
if (node.path === parentPath) {
|
||||
const newPath = addPaths(newNode, node.path);
|
||||
return { ...node, children: [...(node.children || []), newPath] };
|
||||
}
|
||||
if (node.children) {
|
||||
return {
|
||||
...node,
|
||||
children: node.children.map((child) =>
|
||||
addNode(child, parentPath, newNode),
|
||||
),
|
||||
};
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
export const renameNode = (
|
||||
node: FileNode,
|
||||
oldPath: string,
|
||||
newName: string,
|
||||
): FileNode | null => {
|
||||
if (node.path === oldPath) {
|
||||
const pathParts = node.path?.split("/") || [];
|
||||
pathParts[pathParts.length - 1] = newName;
|
||||
const newPath = pathParts.join("/");
|
||||
const renamedNode = { ...node, name: newName, path: newPath };
|
||||
|
||||
if (renamedNode.children) {
|
||||
renamedNode.children = renamedNode.children.map((child) => {
|
||||
const oldChildPath = child.path || "";
|
||||
const newChildPath = oldChildPath.replace(oldPath, newPath);
|
||||
return (
|
||||
renameNode(
|
||||
child,
|
||||
oldChildPath,
|
||||
newChildPath.split("/").pop() || "",
|
||||
) || child
|
||||
);
|
||||
});
|
||||
}
|
||||
return renamedNode;
|
||||
}
|
||||
|
||||
if (node.children) {
|
||||
return {
|
||||
...node,
|
||||
children: node.children.map(
|
||||
(child) => renameNode(child, oldPath, newName) || child,
|
||||
),
|
||||
};
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
export const filterTree = (node: FileNode, query: string): FileNode | null => {
|
||||
if (!query) return node;
|
||||
const lowerQuery = query.toLowerCase();
|
||||
|
||||
if (node.type === "file") {
|
||||
if (node.name.toLowerCase().includes(lowerQuery)) return node;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (node.children) {
|
||||
const filteredChildren = node.children
|
||||
.map((child) => filterTree(child, query))
|
||||
.filter((child): child is FileNode => child !== null);
|
||||
|
||||
if (filteredChildren.length > 0) {
|
||||
return { ...node, children: filteredChildren };
|
||||
}
|
||||
}
|
||||
|
||||
if (node.name.toLowerCase().includes(lowerQuery)) return node;
|
||||
return null;
|
||||
};
|
||||
|
||||
export const collectPathsToExpand = (
|
||||
node: FileNode,
|
||||
query: string,
|
||||
): Set<string> => {
|
||||
const paths = new Set<string>();
|
||||
if (!query) return paths;
|
||||
|
||||
const lowerQuery = query.toLowerCase();
|
||||
|
||||
const search = (n: FileNode, currentPath: string) => {
|
||||
if (n.name.toLowerCase().includes(lowerQuery)) {
|
||||
const pathParts = currentPath.split("/");
|
||||
for (let i = 1; i < pathParts.length; i++) {
|
||||
paths.add(pathParts.slice(0, i).join("/"));
|
||||
}
|
||||
}
|
||||
if (n.children) {
|
||||
n.children.forEach((child) => {
|
||||
const childPath = child.path || `${currentPath}/${child.name}`;
|
||||
search(child, childPath);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
search(node, node.path || node.name);
|
||||
return paths;
|
||||
};
|
||||
|
||||
export const getLanguage = (path: string) => {
|
||||
const ext = path.split(".").pop();
|
||||
const map: Record<string, string> = {
|
||||
py: "python",
|
||||
js: "javascript",
|
||||
ts: "typescript",
|
||||
jsx: "javascript",
|
||||
tsx: "typescript",
|
||||
json: "json",
|
||||
md: "markdown",
|
||||
css: "css",
|
||||
html: "html",
|
||||
};
|
||||
return map[ext || ""] || "plaintext";
|
||||
};
|
||||
Reference in New Issue
Block a user