Files
fusion/packages/dashboard/app/utils/pathDisplay.ts
Fusion 995165ea60 feat(FN-2944): merge fusion/fn-2944
- test(FN-2944): cover already checked out worktree conflict recovery
- fix(FN-2944): recognize git already checked out worktree conflict
- fix(engine): auto-recover from squash-merge orphan rebase failures

Fusion-Task-Id: FN-2944
2026-04-29 07:10:52 -07:00

93 lines
2.8 KiB
TypeScript

export interface PathBreadcrumb {
label: string;
path: string;
}
export function normalizeDisplayPath(path: string): string {
return path.replace(/\\/g, "/");
}
function trimTrailingSeparators(path: string): string {
return path.replace(/[\\/]+$/g, "");
}
export function splitPathSegments(path: string): string[] {
const normalized = normalizeDisplayPath(trimTrailingSeparators(path));
if (!normalized) return [];
return normalized.split("/").filter(Boolean);
}
export function getPathBasename(path: string): string {
const normalized = normalizeDisplayPath(trimTrailingSeparators(path));
if (!normalized) return path;
const segments = normalized.split("/").filter(Boolean);
return segments[segments.length - 1] || normalized;
}
export function getTrailingPath(path: string, count: number): string {
const segments = splitPathSegments(path);
if (segments.length === 0) {
return normalizeDisplayPath(path);
}
return segments.slice(-count).join("/");
}
export function getDisplayDirname(path: string): string {
const normalized = normalizeDisplayPath(trimTrailingSeparators(path));
const lastSeparator = normalized.lastIndexOf("/");
if (lastSeparator < 0) return "";
return normalized.slice(0, lastSeparator + 1);
}
export function joinDisplayPath(basePath: string, name: string): string {
if (!basePath || basePath === ".") {
return name;
}
const segments = splitPathSegments(basePath);
return [...segments, name].join("/");
}
export function getParentDisplayPath(path: string): string {
const segments = splitPathSegments(path);
if (segments.length === 0) {
return ".";
}
segments.pop();
return segments.length === 0 ? "." : segments.join("/");
}
export function getPathBreadcrumbs(path: string): PathBreadcrumb[] {
const normalized = normalizeDisplayPath(path);
const winMatch = normalized.match(/^([A-Za-z]:)(?:\/(.*))?$/);
if (winMatch) {
const root = `${winMatch[1]}/`;
const segments = (winMatch[2] ?? "").split("/").filter(Boolean);
const breadcrumbs: PathBreadcrumb[] = [{ label: winMatch[1], path: root }];
for (let i = 0; i < segments.length; i += 1) {
breadcrumbs.push({
label: segments[i]!,
path: `${root}${segments.slice(0, i + 1).join("/")}`,
});
}
return breadcrumbs;
}
if (normalized.startsWith("/")) {
const segments = normalized.split("/").filter(Boolean);
const breadcrumbs: PathBreadcrumb[] = [{ label: "/", path: "/" }];
for (let i = 0; i < segments.length; i += 1) {
breadcrumbs.push({
label: segments[i]!,
path: `/${segments.slice(0, i + 1).join("/")}`,
});
}
return breadcrumbs;
}
const segments = normalized.split("/").filter(Boolean);
return segments.map((segment, index) => ({
label: segment,
path: segments.slice(0, index + 1).join("/"),
}));
}