1import { pipe } from "effect/Function";
2import {
3 fileBasename,
4 stripSlashPrefixedWindowsDrive,
5 isWindowsAbsolutePath,
6} from "@t3tools/shared/path";
7import { formatFilePathPosition, splitFilePathPosition } from "@t3tools/shared/fileLinks";
8
9function normalizePathSeparators(path: string): string {
10 return path.replaceAll("\\", "/");
11}
12
13function trimTrailingPathSeparators(path: string): string {
14 return path.replace(/[\\/]+$/, "");
15}
16
17function stripRelativePrefixes(path: string): string {
18 return path.replace(/^\.\/+/, "").replace(/^\/+/, "");
19}
20
21export function formatWorkspaceRelativePath(
22 pathWithPosition: string,
23 workspaceRoot: string | undefined,
24): string {
25 const position = splitFilePathPosition(pathWithPosition);
26 const normalizedPath = stripSlashPrefixedWindowsDrive(normalizePathSeparators(position.path));
27
28 let displayPath = normalizedPath;
29 if (workspaceRoot) {
30 const normalizedWorkspaceRoot = pipe(
31 trimTrailingPathSeparators(workspaceRoot),
32 normalizePathSeparators,
33 stripSlashPrefixedWindowsDrive,
34 );
35 const workspaceLabel = fileBasename(normalizedWorkspaceRoot);
36 const caseInsensitive = isWindowsAbsolutePath(stripSlashPrefixedWindowsDrive(workspaceRoot));
37 const pathForCompare = caseInsensitive ? normalizedPath.toLowerCase() : normalizedPath;
38 const workspaceForCompare = caseInsensitive
39 ? normalizedWorkspaceRoot.toLowerCase()
40 : normalizedWorkspaceRoot;
41 const workspaceWithSeparator = `${workspaceForCompare}/`;
42 const workspaceLabelWithSeparator = `${caseInsensitive ? workspaceLabel.toLowerCase() : workspaceLabel}/`;
43
44 if (pathForCompare === workspaceForCompare) {
45 displayPath = workspaceLabel;
46 } else if (pathForCompare.startsWith(workspaceWithSeparator)) {
47 const relativeSuffix = normalizedPath.slice(normalizedWorkspaceRoot.length + 1);
48 displayPath = `${workspaceLabel}/${relativeSuffix}`;
49 } else if (!normalizedPath.startsWith("/")) {
50 const relativePath = stripRelativePrefixes(normalizedPath);
51 displayPath = pathForCompare.startsWith(workspaceLabelWithSeparator)
52 ? normalizedPath
53 : `${workspaceLabel}/${relativePath}`;
54 }
55 }
56
57 return formatFilePathPosition({ ...position, path: displayPath });
58}