/
base-path.ts
94 lines (82 loc) · 2.89 KB
/
base-path.ts
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
import * as Path from "path";
/**
* Helper class that determines the common base path of a set of files.
*
* In the first step all files must be passed to {@link add}. Afterwards {@link trim}
* can be used to retrieve the shortest path relative to the determined base path.
*/
export class BasePath {
/**
* List of known base paths.
*/
private basePaths: string[] = [];
/**
* Add the given file path to this set of base paths.
*
* @param fileName The absolute filename that should be added to the base path.
*/
add(fileName: string) {
const fileDir = Path.dirname(BasePath.normalize(fileName));
const filePath = fileDir.split("/");
basePaths: for (let n = 0, c = this.basePaths.length; n < c; n++) {
const basePath = this.basePaths[n].split("/");
const mMax = Math.min(basePath.length, filePath.length);
for (let m = 0; m < mMax; m++) {
if (basePath[m] === filePath[m]) {
continue;
}
if (m < 1) {
// No match at all, try next known base path
continue basePaths;
} else {
// Partial match, trim the known base path
if (m < basePath.length) {
this.basePaths[n] = basePath.slice(0, m).join("/");
}
return;
}
}
// Complete match, exit
this.basePaths[n] = basePath.splice(0, mMax).join("/");
return;
}
// Unknown base path, add it
this.basePaths.push(fileDir);
}
/**
* Trim the given filename by the determined base paths.
*
* @param fileName The absolute filename that should be trimmed.
* @returns The trimmed version of the filename.
*/
trim(fileName: string): string {
fileName = BasePath.normalize(fileName);
for (let n = 0, c = this.basePaths.length; n < c; n++) {
const basePath = this.basePaths[n];
if (fileName.substring(0, basePath.length) === basePath) {
return fileName.substring(basePath.length + 1);
}
}
return fileName;
}
/**
* Reset this instance, ignore all paths already passed to {@link add}.
*/
reset() {
this.basePaths = [];
}
/**
* Normalize the given path.
*
* @param path The path that should be normalized.
* @returns Normalized version of the given path.
*/
static normalize(path: string): string {
// Ensure forward slashes
path = path.replace(/\\/g, "/");
// Remove all surrounding quotes
path = path.replace(/^["']+|["']+$/g, "");
// Make Windows drive letters upper case
return path.replace(/^([^:]+):\//, (_m, m1) => m1.toUpperCase() + ":/");
}
}