-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathos-agnostic-paths.ts
More file actions
133 lines (122 loc) · 3.91 KB
/
os-agnostic-paths.ts
File metadata and controls
133 lines (122 loc) · 3.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import type { AuditOutput, AuditReport } from '@code-pushup/models';
const AGNOSTIC_PATH_SEP_REGEX = /[/\\]/g;
const OS_AGNOSTIC_PATH_SEP = '/';
const OS_AGNOSTIC_CWD = `<CWD>`;
/**
* Converts a given file path to an OS-agnostic path by replacing the current working directory with '<CWD>'
* and normalizing path separators to '/'.
*
* @param filePath - The file path to be converted.
* @param separator - The path separator to use for normalization. Defaults to the OS-specific separator.
* @returns The OS-agnostic path.
*
* @example
*
* At CWD on Ubuntu (Linux)
* Input: /home/projects/my-folder/my-file.ts
* Output: <CWD>/my-folder/my-file.ts
*
* At CWD on Windows
* Input: D:\projects\my-folder\my-file.ts
* Output: <CWD>/my-folder/my-file.ts
*
* At CWD on macOS
* Input: /Users/projects/my-folder/my-file.ts
* Output: <CWD>/my-folder/my-file.ts
*
* Out of CWD on all OS
* Input: /Users/projects/../my-folder/my-file.ts
* Output: ../my-folder/my-file.ts
*
* Absolute paths (all OS)
* Input: \\my-folder\\my-file.ts
* Output: /my-folder/my-file.ts
*
* Relative paths (all OS)
* Input: ..\\my-folder\\my-file.ts
* Output: ../my-folder/my-file.ts
*
*/
export function osAgnosticPath(filePath: string): string;
export function osAgnosticPath(): undefined;
export function osAgnosticPath(filePath?: string): string | undefined {
if (filePath == null) {
return filePath;
}
// prepare the path for comparison
// normalize path separators od cwd: "Users\\repo" => "Users/repo"
const osAgnosticCwd = process
.cwd()
.split(AGNOSTIC_PATH_SEP_REGEX)
.join(OS_AGNOSTIC_PATH_SEP);
// normalize path separators => "..\\folder\\repo.ts" => => "../folder/repo.ts"
const osAgnosticFilePath = filePath
.split(AGNOSTIC_PATH_SEP_REGEX)
.join(OS_AGNOSTIC_PATH_SEP);
// remove the current working directory for easier comparison
const osAgnosticPathWithoutCwd = osAgnosticFilePath
.replace(osAgnosticCwd, '')
// consider already agnostic paths
.replace(OS_AGNOSTIC_CWD, '');
// path is outside cwd (Users/repo/../my-folder/my-file.ts)
if (
osAgnosticPathWithoutCwd.startsWith(
`${OS_AGNOSTIC_PATH_SEP}..${OS_AGNOSTIC_PATH_SEP}`,
)
) {
return osAgnosticPathWithoutCwd.slice(1); // remove the leading '/'
}
// path is at cwd (Users/repo/my-folder/my-file.ts)
if (
osAgnosticFilePath.startsWith(osAgnosticCwd) ||
osAgnosticFilePath.startsWith(OS_AGNOSTIC_CWD)
) {
// Add a substitute for the current working directory
return `${OS_AGNOSTIC_CWD}${osAgnosticPathWithoutCwd}`;
}
// Notice: I kept the following conditions for documentation purposes
// path is absolute (/my-folder/my-file.ts)
if (osAgnosticPathWithoutCwd.startsWith(OS_AGNOSTIC_PATH_SEP)) {
return osAgnosticPathWithoutCwd;
}
// path is relative (./my-folder/my-file.ts)
if (osAgnosticPathWithoutCwd.startsWith(`.${OS_AGNOSTIC_PATH_SEP}`)) {
return osAgnosticPathWithoutCwd;
}
// path is segment (my-folder/my-file.ts or my-folder/sub-folder)
return osAgnosticPathWithoutCwd;
}
export function osAgnosticAudit<T extends AuditOutput | AuditReport>(
audit: T,
transformMessage: (message: string) => string = s => s,
): T {
const { issues = [] } = audit.details ?? {};
if (issues.every(({ source }) => source == null)) {
return audit;
}
return {
...audit,
details: {
issues: issues.map(issue =>
issue.source == null
? issue
: {
...issue,
source: {
...issue.source,
file: osAgnosticPath(issue.source.file),
},
message: transformMessage(issue.message),
},
),
},
};
}
export function osAgnosticAuditOutputs<T extends AuditOutput | AuditReport>(
audits: T[],
transformAuditIssueMessage?: (message: string) => string,
): T[] {
return audits.map(audit =>
osAgnosticAudit(audit, transformAuditIssueMessage),
);
}