-
Notifications
You must be signed in to change notification settings - Fork 209
/
paths.ts
139 lines (130 loc) · 3.01 KB
/
paths.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
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
134
135
136
137
138
139
/**
* The functions in this module are mostly copied from the generated
* Emscripten PHP module. This enables features like filesystem journaling,
* which use some low-level Emscripten APIs and need access to the
* same path helpers.
*/
/**
* Joins paths together.
*
* For example:
*
* > joinPaths('wordpress', 'wp-content')
* 'wordpress/wp-content'
*
* Use this for all PHP paths and **do not** use path.join().
* This is important because Emscripten paths are **always**
* POSIX-style paths. Imagine joining paths on Windows:
*
* > path.join('wordpress', 'wp-content')
* '\\wordpress\\wp-content' // invalid in PHP.wasm
*
* See the path.join issue for more details:
*
* https://github.com/WordPress/playground-tools/issues/11#issuecomment-1579074763
*
* @param paths Paths segments to join
* @returns A joined path
*/
export function joinPaths(...paths: string[]) {
let path = paths.join('/');
const isAbsolute = path[0] === '/';
const trailingSlash = path.substring(path.length - 1) === '/';
path = normalizePath(path);
if (!path && !isAbsolute) {
path = '.';
}
if (path && trailingSlash) {
path += '/';
}
return path;
}
/**
* Returns the last portion of a path.
*
* @param path - The path to extract the basename from.
* @returns The basename of the path.
*/
export function basename(path: string) {
if (path === '/') {
return '/';
}
path = normalizePath(path);
const lastSlash = path.lastIndexOf('/');
if (lastSlash === -1) {
return path;
}
return path.substr(lastSlash + 1);
}
/**
* Returns the directory name of a path.
*
* @param path - The path to extract the directory name from.
* @returns The directory name of the path.
*/
export function dirname(path: string) {
if (path === '/') {
return '/';
}
path = normalizePath(path);
const lastSlash = path.lastIndexOf('/');
if (lastSlash === -1) {
return '';
}
if (lastSlash === 0) {
return '/';
}
return path.substr(0, lastSlash);
}
/**
* Normalizes a path.
*
* For example:
*
* > normalizePath('wordpress/wp-content/../')
* 'wordpress'
*
* @param path
* @returns
*/
export function normalizePath(path: string) {
const isAbsolute = path[0] === '/';
path = normalizePathsArray(
path.split('/').filter((p: any) => !!p),
!isAbsolute
).join('/');
return (isAbsolute ? '/' : '') + path.replace(/\/$/, '');
}
/**
* Normalizes paths.
*
* For example:
*
* > normalizePathsArray(['wordpress', 'wp-content', '..', '', '.', 'wp-includes'])
* ['wordpress', 'wp-includes']
*
* @param parts parts of the path to normalize
* @param allowAboveRoot allow paths above the root
* @returns normalized paths
*/
export function normalizePathsArray(parts: string[], allowAboveRoot: boolean) {
let up = 0;
for (let i = parts.length - 1; i >= 0; i--) {
const last = parts[i];
if (last === '.') {
parts.splice(i, 1);
} else if (last === '..') {
parts.splice(i, 1);
up++;
} else if (up) {
parts.splice(i, 1);
up--;
}
}
if (allowAboveRoot) {
for (; up; up--) {
parts.unshift('..');
}
}
return parts;
}