core/converters/folder.converter.ts
core/converters/folder.converter.ts is a file in GovLab Patterns. 32 lines of code and 10 definitions.
import type { TreeGroup, TreeLeaf, TreeNode } from "#types/page.types";
import type { FileEntry } from "#types/package.types";
const PATH_SEP = "/";
const relParts = function relParts(rel: string, root: string): string[] {
return (root === "" ? rel : rel.slice(root.length + 1)).split(PATH_SEP);
};
const leafOf = function leafOf(entry: FileEntry, rel: string): TreeLeaf {
return {
count: entry.walk.length,
entry,
kind: "file",
name: relParts(entry.rel, rel)[0] ?? entry.rel,
rel: entry.rel,
};
};
export const buildGroup = function buildGroup(entries: readonly FileEntry[], rel: string, name: string): TreeGroup {
const leaves = entries.filter((entry) => relParts(entry.rel, rel).length === 1).map((entry) => leafOf(entry, rel));
const deeper = entries.filter((entry) => relParts(entry.rel, rel).length > 1);
const dirNames = [...new Set(deeper.map((entry) => relParts(entry.rel, rel)[0] ?? ""))];
const dirs = dirNames.map((dirName) =>
buildGroup(
deeper.filter((entry) => (relParts(entry.rel, rel)[0] ?? "") === dirName),
rel === "" ? dirName : `${rel}${PATH_SEP}${dirName}`,
dirName,
),
);
const children: TreeNode[] = [...leaves, ...dirs];
return { children, count: children.reduce((sum, child) => sum + child.count, 0), kind: "dir", name, rel };
};
export const subtreeFiles = function subtreeFiles(node: TreeNode): FileEntry[] {
return node.kind === "file" ? [node.entry] : node.children.flatMap(subtreeFiles);
};