/
path.ts
87 lines (68 loc) · 2.09 KB
/
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
const ABSOLUTE_PATH_REGEX = /^(?:\/|(?:[A-Za-z]:)?[/\\|])/;
const RELATIVE_PATH_REGEX = /^\.?\.\//;
const ALL_BACKSLASHES_REGEX = /\\/g;
const ANY_SLASH_REGEX = /[/\\]/;
const EXTNAME_REGEX = /\.[^.]+$/;
export function isAbsolute(path: string): boolean {
return ABSOLUTE_PATH_REGEX.test(path);
}
export function isRelative(path: string): boolean {
return RELATIVE_PATH_REGEX.test(path);
}
export function normalize(path: string): string {
return path.replace(ALL_BACKSLASHES_REGEX, '/');
}
export function basename(path: string): string {
return path.split(ANY_SLASH_REGEX).pop() || '';
}
export function dirname(path: string): string {
const match = /[/\\][^/\\]*$/.exec(path);
if (!match) return '.';
const directory = path.slice(0, -match[0].length);
// If `directory` is the empty string, we're at root.
return directory || '/';
}
export function extname(path: string): string {
const match = EXTNAME_REGEX.exec(basename(path)!);
return match ? match[0] : '';
}
export function relative(from: string, to: string): string {
const fromParts = from.split(ANY_SLASH_REGEX).filter(Boolean);
const toParts = to.split(ANY_SLASH_REGEX).filter(Boolean);
if (fromParts[0] === '.') fromParts.shift();
if (toParts[0] === '.') toParts.shift();
while (fromParts[0] && toParts[0] && fromParts[0] === toParts[0]) {
fromParts.shift();
toParts.shift();
}
while (toParts[0] === '..' && fromParts.length > 0) {
toParts.shift();
fromParts.pop();
}
while (fromParts.pop()) {
toParts.unshift('..');
}
return toParts.join('/');
}
export function resolve(...paths: string[]): string {
const firstPathSegment = paths.shift();
if (!firstPathSegment) {
return '/';
}
let resolvedParts = firstPathSegment.split(ANY_SLASH_REGEX);
for (const path of paths) {
if (isAbsolute(path)) {
resolvedParts = path.split(ANY_SLASH_REGEX);
} else {
const parts = path.split(ANY_SLASH_REGEX);
while (parts[0] === '.' || parts[0] === '..') {
const part = parts.shift();
if (part === '..') {
resolvedParts.pop();
}
}
resolvedParts.push(...parts);
}
}
return resolvedParts.join('/');
}