@cspell/url 9.0.1 → 9.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +210 -182
- package/dist/index.js +390 -321
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,234 +1,262 @@
|
|
|
1
|
+
//#region src/dataUrl.d.mts
|
|
1
2
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
* Try to determine the base name of a URL.
|
|
4
|
+
* @param url
|
|
5
|
+
* @returns the base name of a URL, including the trailing `/` if present.
|
|
6
|
+
*/
|
|
6
7
|
declare function urlBasename(url: string | URL): string;
|
|
7
8
|
declare function isDataURL(url: string | URL): boolean;
|
|
8
|
-
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/defaultFileUrlBuilder.d.mts
|
|
9
11
|
declare function encodePathChars(filepath: string): string;
|
|
10
12
|
/**
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
* Normalize a file path for use in a URL.
|
|
14
|
+
* ```js
|
|
15
|
+
* const url = new URL(normalizeFilePathForUrl('path\\to\\file.txt'), 'file:///Users/user/');
|
|
16
|
+
* // Result: file:///Users/user/path/to/file.txt
|
|
17
|
+
* ```
|
|
18
|
+
* @param filePath
|
|
19
|
+
* @returns a normalized file path for use as a relative path in a URL.
|
|
20
|
+
*/
|
|
19
21
|
declare function normalizeFilePathForUrl(filePath: string): string;
|
|
20
22
|
/**
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
* Try to make a file URL.
|
|
24
|
+
* - if filenameOrUrl is already a URL, it is returned as is.
|
|
25
|
+
* -
|
|
26
|
+
* @param filenameOrUrl
|
|
27
|
+
* @param relativeTo - optional URL, if given, filenameOrUrl will be parsed as relative.
|
|
28
|
+
* @returns a URL
|
|
29
|
+
*/
|
|
28
30
|
declare function toFileURL(filenameOrUrl: string | URL, relativeTo?: string | URL): URL;
|
|
29
31
|
/**
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
* Converts a file path to a URL and adds a trailing slash.
|
|
33
|
+
* @param dir - url to a directory
|
|
34
|
+
* @returns a URL
|
|
35
|
+
*/
|
|
34
36
|
declare function toFileDirURL(dir: string | URL): URL;
|
|
35
|
-
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/fileUrl.d.mts
|
|
36
39
|
/**
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
* @param url - URL or string to check if it is a file URL.
|
|
41
|
+
* @returns true if the URL is a file URL.
|
|
42
|
+
*/
|
|
40
43
|
declare function isFileURL(url: URL | string): boolean;
|
|
41
44
|
/**
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
* Convert a URL into a string. If it is a file URL, convert it to a path.
|
|
46
|
+
* @param url - URL
|
|
47
|
+
* @returns path or href
|
|
48
|
+
*/
|
|
46
49
|
declare function toFilePathOrHref(url: URL | string): string;
|
|
47
|
-
|
|
50
|
+
//#endregion
|
|
51
|
+
//#region src/FileUrlBuilder.d.mts
|
|
48
52
|
interface ParsedPath {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
53
|
+
/**
|
|
54
|
+
* The root of the path such as '/' or 'c:\'
|
|
55
|
+
*/
|
|
56
|
+
root: string;
|
|
57
|
+
/**
|
|
58
|
+
* The full directory path such as '/home/user/dir' or 'c:\path\dir'
|
|
59
|
+
*/
|
|
60
|
+
dir: string;
|
|
61
|
+
/**
|
|
62
|
+
* The file name including extension (if any) such as 'index.html'
|
|
63
|
+
*/
|
|
64
|
+
base: string;
|
|
65
|
+
/**
|
|
66
|
+
* The file extension (if any) such as '.html'
|
|
67
|
+
*/
|
|
68
|
+
ext: string;
|
|
69
|
+
/**
|
|
70
|
+
* The file name without extension (if any) such as 'index'
|
|
71
|
+
*/
|
|
72
|
+
name: string;
|
|
69
73
|
}
|
|
70
74
|
interface PathInterface {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
sep: string;
|
|
76
|
+
resolve(...paths: string[]): string;
|
|
77
|
+
parse(path: string): ParsedPath;
|
|
78
|
+
normalize(path: string): string;
|
|
79
|
+
relative(from: string, to: string): string;
|
|
80
|
+
isAbsolute(path: string): boolean;
|
|
77
81
|
}
|
|
78
82
|
interface BuilderOptions {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
83
|
+
windows?: boolean | undefined;
|
|
84
|
+
path?: PathInterface | undefined;
|
|
85
|
+
cwd?: URL | undefined;
|
|
82
86
|
}
|
|
83
87
|
declare class FileUrlBuilder {
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
88
|
+
#private;
|
|
89
|
+
private windows;
|
|
90
|
+
readonly path: PathInterface;
|
|
91
|
+
readonly cwd: URL;
|
|
92
|
+
constructor(options?: BuilderOptions);
|
|
93
|
+
/**
|
|
94
|
+
* Encode special characters in a file path to use in a URL.
|
|
95
|
+
* @param filepath
|
|
96
|
+
* @returns
|
|
97
|
+
*/
|
|
98
|
+
encodePathChars(filepath: string): string;
|
|
99
|
+
/**
|
|
100
|
+
* Normalize a file path for use in a URL.
|
|
101
|
+
* ```js
|
|
102
|
+
* const url = new URL(normalizeFilePathForUrl('path\\to\\file.txt'), 'file:///Users/user/');
|
|
103
|
+
* // Result: file:///Users/user/path/to/file.txt
|
|
104
|
+
* ```
|
|
105
|
+
* @param filePath
|
|
106
|
+
* @returns a normalized file path for use as a relative path in a URL.
|
|
107
|
+
*/
|
|
108
|
+
normalizeFilePathForUrl(filePath: string): string;
|
|
109
|
+
/**
|
|
110
|
+
* Try to make a file URL.
|
|
111
|
+
* - if filenameOrUrl is already a URL, it is returned as is.
|
|
112
|
+
* @param filenameOrUrl
|
|
113
|
+
* @param relativeTo - optional URL, if given, filenameOrUrl will be parsed as relative.
|
|
114
|
+
* @returns a URL
|
|
115
|
+
*/
|
|
116
|
+
toFileURL(filenameOrUrl: string | URL, relativeTo?: string | URL): URL;
|
|
117
|
+
/**
|
|
118
|
+
* Try to make a URL for a directory.
|
|
119
|
+
* - if dirOrUrl is already a URL, a slash is appended to the pathname.
|
|
120
|
+
* @param dirOrUrl - directory path to convert to a file URL.
|
|
121
|
+
* @param relativeTo - optional URL, if given, filenameOrUrl will be parsed as relative.
|
|
122
|
+
* @returns a URL
|
|
123
|
+
*/
|
|
124
|
+
toFileDirURL(dirOrUrl: string | URL, relativeTo?: string | URL): URL;
|
|
125
|
+
urlToFilePathOrHref(url: URL | string): string;
|
|
126
|
+
/**
|
|
127
|
+
* Calculate the relative path to go from `urlFrom` to `urlTo`.
|
|
128
|
+
* The protocol is not evaluated. Only the `url.pathname` is used.
|
|
129
|
+
* The result: `new URL(relative(urlFrom, urlTo), urlFrom).pathname === urlTo.pathname`
|
|
130
|
+
* @param urlFrom
|
|
131
|
+
* @param urlTo
|
|
132
|
+
* @returns the relative path
|
|
133
|
+
*/
|
|
134
|
+
relative(urlFrom: URL, urlTo: URL): string;
|
|
135
|
+
/**
|
|
136
|
+
* Get the parent directory of a URL.
|
|
137
|
+
* @param url
|
|
138
|
+
*/
|
|
139
|
+
urlDirname(url: URL | string): URL;
|
|
140
|
+
pathToFileURL(pathname: string, relativeToURL?: URL | string): URL;
|
|
141
|
+
rootFileURL(filePath?: string): URL;
|
|
142
|
+
/**
|
|
143
|
+
* Determine if a filePath is absolute.
|
|
144
|
+
*
|
|
145
|
+
* @param filePath
|
|
146
|
+
* @returns true if `URL` or `path.isAbsolute(filePath)`
|
|
147
|
+
*/
|
|
148
|
+
isAbsolute(filePath: string): boolean;
|
|
149
|
+
isUrlLike(url: string | URL): boolean;
|
|
146
150
|
}
|
|
147
|
-
|
|
151
|
+
//#endregion
|
|
152
|
+
//#region src/url.d.mts
|
|
148
153
|
/**
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
+
* Try to make a URL.
|
|
155
|
+
* @param url
|
|
156
|
+
* @param relativeTo - optional URL, if given, url will be parsed as relative.
|
|
157
|
+
* @returns a URL
|
|
158
|
+
*/
|
|
154
159
|
declare function toURL(url: string | URL, relativeTo?: string | URL): URL;
|
|
155
160
|
/**
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
+
* Try to determine the parent directory URL of the uri.
|
|
162
|
+
* If it is not a hierarchical URL, then it will return the URL.
|
|
163
|
+
* @param url - url to extract the dirname from.
|
|
164
|
+
* @returns a URL
|
|
165
|
+
*/
|
|
161
166
|
declare function urlParent(url: string | URL): URL;
|
|
162
167
|
/**
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
168
|
+
* Alias of {@link urlParent}
|
|
169
|
+
* Try to determine the parent directory URL of the uri.
|
|
170
|
+
* If it is not a hierarchical URL, then it will return the URL.
|
|
171
|
+
* @param url - url to extract the dirname from.
|
|
172
|
+
* @returns a URL
|
|
173
|
+
*/
|
|
169
174
|
declare const urlDirname: typeof urlParent;
|
|
170
175
|
/**
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
176
|
+
* Remove the file portion of the URL and return the directory portion.
|
|
177
|
+
* If the URL pathname ends with a `/`, it is considered a directory and the URL is returned as is.
|
|
178
|
+
* @param url - url to extract the dirname from.
|
|
179
|
+
*/
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* return the basename (last portion of the URL pathname) of a path. It does NOT remove the trailing slash.
|
|
183
|
+
* @param path - URL pathname to extract the basename from.
|
|
184
|
+
*/
|
|
174
185
|
declare function basenameOfUrlPathname(path: string): string;
|
|
175
186
|
/**
|
|
176
|
-
|
|
177
|
-
|
|
187
|
+
* @param filename - filename to check if it is a string containing a URL.
|
|
188
|
+
*/
|
|
178
189
|
declare function isUrlLike(filename: string): boolean;
|
|
179
190
|
declare function isUrlLike(filename: URL): true;
|
|
180
191
|
/**
|
|
181
|
-
|
|
182
|
-
|
|
192
|
+
* @param filename - filename to check if it is a string containing a URL or a URL object.
|
|
193
|
+
*/
|
|
183
194
|
declare function isUrlLike(filename: string | URL): boolean;
|
|
184
195
|
/**
|
|
185
|
-
|
|
186
|
-
|
|
196
|
+
* @param filename - filename to check if it is a string containing a URL.
|
|
197
|
+
*/
|
|
187
198
|
declare function isNotUrlLike(filename: string): boolean;
|
|
188
199
|
declare function isNotUrlLike(filename: URL): false;
|
|
189
200
|
/**
|
|
190
|
-
|
|
191
|
-
|
|
201
|
+
* @param filename - filename to check if it is a string containing a URL or a URL object.
|
|
202
|
+
*/
|
|
192
203
|
declare function isNotUrlLike(filename: string | URL): filename is string;
|
|
193
204
|
/**
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
205
|
+
* Check if `url` is a URL instance.
|
|
206
|
+
* @returns
|
|
207
|
+
*/
|
|
197
208
|
declare function isURL(url: unknown): url is URL;
|
|
198
209
|
/**
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
210
|
+
*
|
|
211
|
+
* @param url - url to check
|
|
212
|
+
* @param protocol - protocol to check against - e.g. 'file:', 'http:', 'https:'
|
|
213
|
+
* @returns
|
|
214
|
+
*/
|
|
204
215
|
declare function hasProtocol(url: string | URL, protocol: string): boolean;
|
|
205
216
|
/**
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
217
|
+
* Attempts to add a trailing slash to the URL pathname if it does not already have one.
|
|
218
|
+
* Some If the pathname doesn't start with a `/`, a trailing slash is not added.
|
|
219
|
+
* @param url - a URL
|
|
220
|
+
* @returns
|
|
221
|
+
*/
|
|
211
222
|
declare function addTrailingSlash(url: URL): URL;
|
|
212
223
|
/**
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
224
|
+
* Remove the filename at the end of the URL pathname.
|
|
225
|
+
* If the URL pathname ends with a `/`, it is considered a directory and the URL is returned as is.
|
|
226
|
+
* If the URL pathname does not start with a `/`, it is considered an non-regular URL and the URL is returned as is.
|
|
227
|
+
* @param url
|
|
228
|
+
* @returns
|
|
229
|
+
*/
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Calculate the relative path to go from `urlFrom` to `urlTo`.
|
|
233
|
+
* The protocol is not evaluated. Only the `url.pathname` is used.
|
|
234
|
+
* @param urlFrom
|
|
235
|
+
* @param urlTo
|
|
236
|
+
* @returns the relative path
|
|
237
|
+
*/
|
|
219
238
|
declare function urlRelative(urlFrom: string | URL, urlTo: string | URL): string;
|
|
220
239
|
/**
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
240
|
+
* Calculate the relative path to go from `urlFrom` to `urlTo`.
|
|
241
|
+
* The protocol is not evaluated. Only the `url.pathname` is used.
|
|
242
|
+
* @param urlFrom
|
|
243
|
+
* @param urlTo
|
|
244
|
+
* @returns the relative path
|
|
245
|
+
*/
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Ensure that a windows file url is correctly formatted with a capitol letter for the drive.
|
|
249
|
+
*
|
|
250
|
+
* @param url - URL to check.
|
|
251
|
+
* @returns a new URL if modified or converted from a string.
|
|
252
|
+
*/
|
|
226
253
|
declare function normalizeWindowsUrl(url: URL | string): URL;
|
|
227
254
|
/**
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
255
|
+
* There is a bug is NodeJS that sometimes causes UNC paths converted to a URL to be prefixed with `file:////`.
|
|
256
|
+
* @param url - URL to check.
|
|
257
|
+
* @returns fixed URL if needed.
|
|
258
|
+
*/
|
|
232
259
|
declare function fixUncUrl(url: URL): URL;
|
|
233
|
-
|
|
234
|
-
export {
|
|
260
|
+
//#endregion
|
|
261
|
+
export { BuilderOptions, FileUrlBuilder, PathInterface, addTrailingSlash, basenameOfUrlPathname, encodePathChars, fixUncUrl, hasProtocol, isDataURL, isFileURL, isNotUrlLike, isURL, isUrlLike, normalizeFilePathForUrl, normalizeWindowsUrl, toFileDirURL, toFilePathOrHref, toFileURL, toURL, urlBasename, urlDirname, urlParent, urlRelative };
|
|
262
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,376 +1,445 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import Path from "node:path";
|
|
3
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
|
+
|
|
5
|
+
//#region src/url.mts
|
|
6
|
+
const isURLRegEx = /^(\w[\w-]{1,63}:\/|data:|stdin:)/i;
|
|
7
|
+
/**
|
|
8
|
+
* Try to make a URL.
|
|
9
|
+
* @param url
|
|
10
|
+
* @param relativeTo - optional URL, if given, url will be parsed as relative.
|
|
11
|
+
* @returns a URL
|
|
12
|
+
*/
|
|
3
13
|
function toURL(url, relativeTo) {
|
|
4
|
-
|
|
14
|
+
return normalizeWindowsUrl(url instanceof URL ? url : new URL(url, relativeTo));
|
|
5
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Try to determine the parent directory URL of the uri.
|
|
18
|
+
* If it is not a hierarchical URL, then it will return the URL.
|
|
19
|
+
* @param url - url to extract the dirname from.
|
|
20
|
+
* @returns a URL
|
|
21
|
+
*/
|
|
6
22
|
function urlParent(url) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
return new URL(hasTrailingSlash ? ".." : ".", url);
|
|
23
|
+
url = toURL(url);
|
|
24
|
+
if (url.protocol === "data:") return url;
|
|
25
|
+
const hasTrailingSlash = url.pathname.endsWith("/");
|
|
26
|
+
if (!url.pathname.startsWith("/")) {
|
|
27
|
+
if (!url.pathname) return url;
|
|
28
|
+
const parts = url.pathname.split("/").slice(0, hasTrailingSlash ? -2 : -1);
|
|
29
|
+
const pathname = parts.join("/") + "/";
|
|
30
|
+
return new URL(url.protocol + (url.host ? "//" + url.host : "") + pathname + url.search + url.hash);
|
|
31
|
+
}
|
|
32
|
+
return new URL(hasTrailingSlash ? ".." : ".", url);
|
|
19
33
|
}
|
|
20
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Alias of {@link urlParent}
|
|
36
|
+
* Try to determine the parent directory URL of the uri.
|
|
37
|
+
* If it is not a hierarchical URL, then it will return the URL.
|
|
38
|
+
* @param url - url to extract the dirname from.
|
|
39
|
+
* @returns a URL
|
|
40
|
+
*/
|
|
41
|
+
const urlDirname = urlParent;
|
|
42
|
+
/**
|
|
43
|
+
* return the basename (last portion of the URL pathname) of a path. It does NOT remove the trailing slash.
|
|
44
|
+
* @param path - URL pathname to extract the basename from.
|
|
45
|
+
*/
|
|
21
46
|
function basenameOfUrlPathname(path) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
47
|
+
const adj = path.endsWith("/") ? 2 : 0;
|
|
48
|
+
const idx = path.lastIndexOf("/", path.length - adj);
|
|
49
|
+
return idx >= 0 ? path.slice(idx + 1) : path;
|
|
25
50
|
}
|
|
26
51
|
function isUrlLike(filename) {
|
|
27
|
-
|
|
52
|
+
return filename instanceof URL || isURLRegEx.test(filename);
|
|
28
53
|
}
|
|
29
54
|
function isNotUrlLike(filename) {
|
|
30
|
-
|
|
55
|
+
return !isUrlLike(filename);
|
|
31
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Check if `url` is a URL instance.
|
|
59
|
+
* @returns
|
|
60
|
+
*/
|
|
32
61
|
function isURL(url) {
|
|
33
|
-
|
|
62
|
+
return url instanceof URL;
|
|
34
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
*
|
|
66
|
+
* @param url - url to check
|
|
67
|
+
* @param protocol - protocol to check against - e.g. 'file:', 'http:', 'https:'
|
|
68
|
+
* @returns
|
|
69
|
+
*/
|
|
35
70
|
function hasProtocol(url, protocol) {
|
|
36
|
-
|
|
37
|
-
|
|
71
|
+
protocol = protocol.endsWith(":") ? protocol : protocol + ":";
|
|
72
|
+
return typeof url === "string" ? url.startsWith(protocol) : url.protocol === protocol;
|
|
38
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Attempts to add a trailing slash to the URL pathname if it does not already have one.
|
|
76
|
+
* Some If the pathname doesn't start with a `/`, a trailing slash is not added.
|
|
77
|
+
* @param url - a URL
|
|
78
|
+
* @returns
|
|
79
|
+
*/
|
|
39
80
|
function addTrailingSlash(url) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
81
|
+
if (url.pathname.endsWith("/")) return url;
|
|
82
|
+
const urlWithSlash = new URL(url.href);
|
|
83
|
+
urlWithSlash.pathname += "/";
|
|
84
|
+
return urlWithSlash;
|
|
44
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Calculate the relative path to go from `urlFrom` to `urlTo`.
|
|
88
|
+
* The protocol is not evaluated. Only the `url.pathname` is used.
|
|
89
|
+
* @param urlFrom
|
|
90
|
+
* @param urlTo
|
|
91
|
+
* @returns the relative path
|
|
92
|
+
*/
|
|
45
93
|
function urlRelative(urlFrom, urlTo) {
|
|
46
|
-
|
|
94
|
+
return urlToUrlRelative(toURL(urlFrom), toURL(urlTo));
|
|
47
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Calculate the relative path to go from `urlFrom` to `urlTo`.
|
|
98
|
+
* The protocol is not evaluated. Only the `url.pathname` is used.
|
|
99
|
+
* @param urlFrom
|
|
100
|
+
* @param urlTo
|
|
101
|
+
* @returns the relative path
|
|
102
|
+
*/
|
|
48
103
|
function urlToUrlRelative(urlFrom, urlTo) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
const rel = "../".repeat(p0Parts.length - i) + p1Parts.slice(i).join("/");
|
|
65
|
-
return decodeURIComponent(rel.length < p1.length ? rel : p1);
|
|
104
|
+
let pFrom = urlFrom.pathname;
|
|
105
|
+
const pTo = urlTo.pathname;
|
|
106
|
+
if (pFrom === pTo) return "";
|
|
107
|
+
pFrom = pFrom.endsWith("/") ? pFrom : new URL("./", urlFrom).pathname;
|
|
108
|
+
if (pTo.startsWith(pFrom)) return decodeURIComponent(pTo.slice(pFrom.length));
|
|
109
|
+
const p0 = pFrom;
|
|
110
|
+
const p1 = pTo;
|
|
111
|
+
if (p1.startsWith(p0)) return decodeURIComponent(p0 === p1 ? "" : p1.slice(p0.lastIndexOf("/") + 1));
|
|
112
|
+
const p0Parts = p0.split("/").slice(0, -1);
|
|
113
|
+
const p1Parts = p1.split("/");
|
|
114
|
+
let i = 0;
|
|
115
|
+
for (i = 0; i < p0Parts.length && i < p1Parts.length - 1 && p0Parts[i] === p1Parts[i]; ++i);
|
|
116
|
+
const rel = "../".repeat(p0Parts.length - i) + p1Parts.slice(i).join("/");
|
|
117
|
+
return decodeURIComponent(rel.length < p1.length ? rel : p1);
|
|
66
118
|
}
|
|
67
|
-
|
|
68
|
-
|
|
119
|
+
const regExpWindowsPath = /^[\\/]([a-zA-Z]:[\\/])/;
|
|
120
|
+
const badUncLocalhostUrl = /^(\/+[a-zA-Z])\$/;
|
|
121
|
+
/**
|
|
122
|
+
* Ensure that a windows file url is correctly formatted with a capitol letter for the drive.
|
|
123
|
+
*
|
|
124
|
+
* @param url - URL to check.
|
|
125
|
+
* @returns a new URL if modified or converted from a string.
|
|
126
|
+
*/
|
|
69
127
|
function normalizeWindowsUrl(url) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
return fixUncUrl(url);
|
|
128
|
+
url = typeof url === "string" ? new URL(url) : url;
|
|
129
|
+
if (url.protocol === "file:") {
|
|
130
|
+
let pathname = url.pathname.replaceAll("%3A", ":").replaceAll("%3a", ":").replaceAll("%24", "$");
|
|
131
|
+
if (!url.host) pathname = pathname.replace(badUncLocalhostUrl, "$1:");
|
|
132
|
+
pathname = pathname.replace(regExpWindowsPath, (d) => d.toUpperCase());
|
|
133
|
+
if (pathname !== url.pathname) {
|
|
134
|
+
url = new URL(url);
|
|
135
|
+
url.pathname = pathname;
|
|
136
|
+
return fixUncUrl(url);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return fixUncUrl(url);
|
|
84
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* There is a bug is NodeJS that sometimes causes UNC paths converted to a URL to be prefixed with `file:////`.
|
|
143
|
+
* @param url - URL to check.
|
|
144
|
+
* @returns fixed URL if needed.
|
|
145
|
+
*/
|
|
85
146
|
function fixUncUrl(url) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
return url;
|
|
147
|
+
if (url.href.startsWith("file:////")) return new URL(url.href.replace(/^file:\/{4}/, "file://"));
|
|
148
|
+
return url;
|
|
90
149
|
}
|
|
91
150
|
|
|
92
|
-
|
|
93
|
-
|
|
151
|
+
//#endregion
|
|
152
|
+
//#region src/dataUrl.mts
|
|
153
|
+
const regMatchFilename = /filename=([^;,]*)/;
|
|
154
|
+
/**
|
|
155
|
+
* Try to determine the base name of a URL.
|
|
156
|
+
* @param url
|
|
157
|
+
* @returns the base name of a URL, including the trailing `/` if present.
|
|
158
|
+
*/
|
|
94
159
|
function urlBasename(url) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
return basenameOfUrlPathname(url.pathname);
|
|
160
|
+
function guessDataUrlName(header) {
|
|
161
|
+
const filenameMatch = header.match(regMatchFilename);
|
|
162
|
+
if (filenameMatch) return filenameMatch[1];
|
|
163
|
+
const mime = header.split(";", 1)[0];
|
|
164
|
+
return mime.replaceAll(/\W/g, ".");
|
|
165
|
+
}
|
|
166
|
+
url = toURL(url);
|
|
167
|
+
if (url.protocol === "data:") return guessDataUrlName(url.pathname.split(",", 1)[0]);
|
|
168
|
+
return basenameOfUrlPathname(url.pathname);
|
|
106
169
|
}
|
|
107
170
|
function isDataURL(url) {
|
|
108
|
-
|
|
171
|
+
return hasProtocol(url, "data:");
|
|
109
172
|
}
|
|
110
173
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
// src/fileUrl.mts
|
|
117
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
118
|
-
var isWindows = process.platform === "win32";
|
|
119
|
-
var windowsUrlPathRegExp = /^\/[a-zA-Z]:\//;
|
|
174
|
+
//#endregion
|
|
175
|
+
//#region src/fileUrl.mts
|
|
176
|
+
const isWindows = process.platform === "win32";
|
|
177
|
+
const windowsUrlPathRegExp = /^\/[a-zA-Z]:\//;
|
|
120
178
|
function isWindowsPathnameWithDriveLatter(pathname) {
|
|
121
|
-
|
|
179
|
+
return windowsUrlPathRegExp.test(pathname);
|
|
122
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* @param url - URL or string to check if it is a file URL.
|
|
183
|
+
* @returns true if the URL is a file URL.
|
|
184
|
+
*/
|
|
123
185
|
function isFileURL(url) {
|
|
124
|
-
|
|
186
|
+
return hasProtocol(url, "file:");
|
|
125
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* Convert a URL into a string. If it is a file URL, convert it to a path.
|
|
190
|
+
* @param url - URL
|
|
191
|
+
* @returns path or href
|
|
192
|
+
*/
|
|
126
193
|
function toFilePathOrHref(url) {
|
|
127
|
-
|
|
194
|
+
return isFileURL(url) && url.toString().startsWith("file:///") ? toFilePath(url) : url.toString();
|
|
128
195
|
}
|
|
129
196
|
function toFilePath(url) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
return url.toString();
|
|
146
|
-
}
|
|
197
|
+
try {
|
|
198
|
+
if (isWindows) {
|
|
199
|
+
const u = new URL(url);
|
|
200
|
+
if (!isWindowsPathnameWithDriveLatter(u.pathname)) {
|
|
201
|
+
const cwdUrl = pathToFileURL(process.cwd());
|
|
202
|
+
if (cwdUrl.hostname) return fileURLToPath(new URL(u.pathname, cwdUrl));
|
|
203
|
+
const drive = cwdUrl.pathname.split("/")[1];
|
|
204
|
+
u.pathname = `/${drive}${u.pathname}`;
|
|
205
|
+
return fileURLToPath(u);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return pathWindowsDriveLetterToUpper(fileURLToPath(url));
|
|
209
|
+
} catch {
|
|
210
|
+
return url.toString();
|
|
211
|
+
}
|
|
147
212
|
}
|
|
148
|
-
|
|
213
|
+
const regExpWindowsPathDriveLetter = /^([a-zA-Z]):[\\/]/;
|
|
149
214
|
function pathWindowsDriveLetterToUpper(absoluteFilePath) {
|
|
150
|
-
|
|
215
|
+
return absoluteFilePath.replace(regExpWindowsPathDriveLetter, (s) => s.toUpperCase());
|
|
151
216
|
}
|
|
152
|
-
|
|
217
|
+
const regExpWindowsFileUrl = /^file:\/\/\/[a-zA-Z]:\//;
|
|
218
|
+
/**
|
|
219
|
+
* Test if a url is a file url with a windows path. It does check for UNC paths.
|
|
220
|
+
* @param url - the url
|
|
221
|
+
* @returns true if the url is a file url with a windows path with a drive letter.
|
|
222
|
+
*/
|
|
153
223
|
function isWindowsFileUrl(url) {
|
|
154
|
-
|
|
224
|
+
return regExpWindowsFileUrl.test(url.toString());
|
|
155
225
|
}
|
|
156
226
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
227
|
+
//#endregion
|
|
228
|
+
//#region src/FileUrlBuilder.mts
|
|
229
|
+
const isWindowsPathRegEx = regExpWindowsPathDriveLetter;
|
|
230
|
+
const isWindowsPathname = regExpWindowsPath;
|
|
231
|
+
const percentRegEx = /%/g;
|
|
232
|
+
const backslashRegEx = /\\/g;
|
|
233
|
+
const newlineRegEx = /\n/g;
|
|
234
|
+
const carriageReturnRegEx = /\r/g;
|
|
235
|
+
const tabRegEx = /\t/g;
|
|
236
|
+
const questionRegex = /\?/g;
|
|
237
|
+
const hashRegex = /#/g;
|
|
238
|
+
const ProtocolFile = "file:";
|
|
168
239
|
var FileUrlBuilder = class {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
return isUrlLike(filePath) || this.path.isAbsolute(filePath);
|
|
333
|
-
}
|
|
334
|
-
isUrlLike(url) {
|
|
335
|
-
return isUrlLike(url);
|
|
336
|
-
}
|
|
240
|
+
windows;
|
|
241
|
+
path;
|
|
242
|
+
cwd;
|
|
243
|
+
constructor(options = {}) {
|
|
244
|
+
const sep = options.path?.sep;
|
|
245
|
+
this.windows = options.windows ?? (sep ? sep === "\\" : void 0) ?? isWindows;
|
|
246
|
+
this.path = options.path ?? (this.windows ? Path.win32 : Path.posix);
|
|
247
|
+
this.cwd = options.cwd ?? this.pathToFileURL(this.path.resolve() + "/", this.rootFileURL());
|
|
248
|
+
assert(this.path.sep === (this.windows ? "\\" : "/"), `Path separator should match OS type Windows: ${this.windows === true ? "true" : (this.windows ?? "undefined") || "false"}, sep: ${this.path.sep}, options: ` + JSON.stringify({
|
|
249
|
+
isWindows,
|
|
250
|
+
sep: `${sep}`,
|
|
251
|
+
windows: options.windows,
|
|
252
|
+
pathSep: options.path?.sep,
|
|
253
|
+
n: options.path?.normalize("path/file.txt"),
|
|
254
|
+
cwd: options.cwd?.href,
|
|
255
|
+
win32: this.path === Path.win32,
|
|
256
|
+
posix: this.path === Path.posix,
|
|
257
|
+
"win32.normalize": this.path.normalize === Path.win32.normalize,
|
|
258
|
+
"posix.normalize": this.path.normalize === Path.posix.normalize
|
|
259
|
+
}) + ``);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Encode special characters in a file path to use in a URL.
|
|
263
|
+
* @param filepath
|
|
264
|
+
* @returns
|
|
265
|
+
*/
|
|
266
|
+
encodePathChars(filepath) {
|
|
267
|
+
filepath = filepath.replaceAll(percentRegEx, "%25");
|
|
268
|
+
if (!this.windows && !isWindows && filepath.includes("\\")) filepath = filepath.replaceAll(backslashRegEx, "%5C");
|
|
269
|
+
filepath = filepath.replaceAll(newlineRegEx, "%0A");
|
|
270
|
+
filepath = filepath.replaceAll(carriageReturnRegEx, "%0D");
|
|
271
|
+
filepath = filepath.replaceAll(tabRegEx, "%09");
|
|
272
|
+
return filepath;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Normalize a file path for use in a URL.
|
|
276
|
+
* ```js
|
|
277
|
+
* const url = new URL(normalizeFilePathForUrl('path\\to\\file.txt'), 'file:///Users/user/');
|
|
278
|
+
* // Result: file:///Users/user/path/to/file.txt
|
|
279
|
+
* ```
|
|
280
|
+
* @param filePath
|
|
281
|
+
* @returns a normalized file path for use as a relative path in a URL.
|
|
282
|
+
*/
|
|
283
|
+
normalizeFilePathForUrl(filePath) {
|
|
284
|
+
filePath = this.encodePathChars(filePath);
|
|
285
|
+
filePath = filePath.replaceAll(questionRegex, "%3F");
|
|
286
|
+
filePath = filePath.replaceAll(hashRegex, "%23");
|
|
287
|
+
const pathname = filePath.replaceAll("\\", "/");
|
|
288
|
+
return pathname.replace(isWindowsPathRegEx, (drive) => `/${drive}`.toUpperCase());
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Try to make a file URL.
|
|
292
|
+
* - if filenameOrUrl is already a URL, it is returned as is.
|
|
293
|
+
* @param filenameOrUrl
|
|
294
|
+
* @param relativeTo - optional URL, if given, filenameOrUrl will be parsed as relative.
|
|
295
|
+
* @returns a URL
|
|
296
|
+
*/
|
|
297
|
+
toFileURL(filenameOrUrl, relativeTo) {
|
|
298
|
+
return normalizeWindowsUrl(this.#toFileURL(filenameOrUrl, relativeTo));
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Try to make a file URL.
|
|
302
|
+
* - if filenameOrUrl is already a URL, it is returned as is.
|
|
303
|
+
* @param filenameOrUrl
|
|
304
|
+
* @param relativeTo - optional URL, if given, filenameOrUrl will be parsed as relative.
|
|
305
|
+
* @returns a URL
|
|
306
|
+
*/
|
|
307
|
+
#toFileURL(filenameOrUrl, relativeTo) {
|
|
308
|
+
if (typeof filenameOrUrl !== "string") return filenameOrUrl;
|
|
309
|
+
if (isUrlLike(filenameOrUrl)) return normalizeWindowsUrl(new URL(filenameOrUrl));
|
|
310
|
+
relativeTo ??= this.cwd;
|
|
311
|
+
isWindows && (filenameOrUrl = filenameOrUrl.replaceAll("\\", "/"));
|
|
312
|
+
if (this.isAbsolute(filenameOrUrl) && isFileURL(relativeTo)) {
|
|
313
|
+
const pathname$1 = this.normalizeFilePathForUrl(filenameOrUrl);
|
|
314
|
+
if (isWindowsFileUrl(relativeTo) && !isWindowsPathnameWithDriveLatter(pathname$1)) {
|
|
315
|
+
const relFilePrefix = relativeTo.toString().slice(0, 10);
|
|
316
|
+
return normalizeWindowsUrl(new URL(relFilePrefix + pathname$1));
|
|
317
|
+
}
|
|
318
|
+
return normalizeWindowsUrl(new URL("file://" + pathname$1));
|
|
319
|
+
}
|
|
320
|
+
if (isUrlLike(relativeTo)) {
|
|
321
|
+
const pathname$1 = this.normalizeFilePathForUrl(filenameOrUrl);
|
|
322
|
+
return normalizeWindowsUrl(new URL(pathname$1, relativeTo));
|
|
323
|
+
}
|
|
324
|
+
const appendSlash = filenameOrUrl.endsWith("/") ? "/" : "";
|
|
325
|
+
const pathname = this.normalizeFilePathForUrl(this.path.resolve(relativeTo.toString(), filenameOrUrl)) + appendSlash;
|
|
326
|
+
return normalizeWindowsUrl(new URL("file://" + pathname));
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Try to make a URL for a directory.
|
|
330
|
+
* - if dirOrUrl is already a URL, a slash is appended to the pathname.
|
|
331
|
+
* @param dirOrUrl - directory path to convert to a file URL.
|
|
332
|
+
* @param relativeTo - optional URL, if given, filenameOrUrl will be parsed as relative.
|
|
333
|
+
* @returns a URL
|
|
334
|
+
*/
|
|
335
|
+
toFileDirURL(dirOrUrl, relativeTo) {
|
|
336
|
+
return addTrailingSlash(this.toFileURL(dirOrUrl, relativeTo));
|
|
337
|
+
}
|
|
338
|
+
urlToFilePathOrHref(url) {
|
|
339
|
+
url = this.toFileURL(url);
|
|
340
|
+
return this.#urlToFilePathOrHref(url);
|
|
341
|
+
}
|
|
342
|
+
#urlToFilePathOrHref(url) {
|
|
343
|
+
if (url.protocol !== ProtocolFile || url.hostname) return url.href;
|
|
344
|
+
const p = this.path === Path ? toFilePathOrHref(url) : decodeURIComponent(url.pathname.split("/").join(this.path.sep));
|
|
345
|
+
return pathWindowsDriveLetterToUpper(p.replace(isWindowsPathname, "$1"));
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Calculate the relative path to go from `urlFrom` to `urlTo`.
|
|
349
|
+
* The protocol is not evaluated. Only the `url.pathname` is used.
|
|
350
|
+
* The result: `new URL(relative(urlFrom, urlTo), urlFrom).pathname === urlTo.pathname`
|
|
351
|
+
* @param urlFrom
|
|
352
|
+
* @param urlTo
|
|
353
|
+
* @returns the relative path
|
|
354
|
+
*/
|
|
355
|
+
relative(urlFrom, urlTo) {
|
|
356
|
+
if (urlFrom.protocol === urlTo.protocol && urlFrom.protocol === ProtocolFile) {
|
|
357
|
+
if (urlFrom.href === urlTo.href) return "";
|
|
358
|
+
urlFrom = urlFrom.pathname.endsWith("/") ? urlFrom : new URL("./", urlFrom);
|
|
359
|
+
const fromPath = urlFrom.pathname;
|
|
360
|
+
const toPath = urlTo.pathname;
|
|
361
|
+
if (toPath.startsWith(fromPath)) return decodeURIComponent(toPath.slice(fromPath.length));
|
|
362
|
+
const pFrom = this.#urlToFilePathOrHref(urlFrom);
|
|
363
|
+
const pTo = this.#urlToFilePathOrHref(urlTo);
|
|
364
|
+
const toIsDir = urlTo.pathname.endsWith("/");
|
|
365
|
+
let pathname = this.normalizeFilePathForUrl(this.path.relative(pFrom, pTo));
|
|
366
|
+
if (toIsDir && !pathname.endsWith("/")) pathname += "/";
|
|
367
|
+
return decodeURIComponent(pathname);
|
|
368
|
+
}
|
|
369
|
+
return decodeURIComponent(urlToUrlRelative(urlFrom, urlTo));
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Get the parent directory of a URL.
|
|
373
|
+
* @param url
|
|
374
|
+
*/
|
|
375
|
+
urlDirname(url) {
|
|
376
|
+
return urlParent(this.toFileURL(url));
|
|
377
|
+
}
|
|
378
|
+
pathToFileURL(pathname, relativeToURL) {
|
|
379
|
+
return new URL(this.normalizeFilePathForUrl(pathname), relativeToURL || this.cwd);
|
|
380
|
+
}
|
|
381
|
+
rootFileURL(filePath) {
|
|
382
|
+
const path = this.path;
|
|
383
|
+
const p = path.parse(path.normalize(path.resolve(filePath ?? ".")));
|
|
384
|
+
return new URL(this.normalizeFilePathForUrl(p.root), this.#getFsRootURL());
|
|
385
|
+
}
|
|
386
|
+
#getFsRootURL() {
|
|
387
|
+
if (this.path === Path) return pathToFileURL("/");
|
|
388
|
+
const p = this.path.resolve("/");
|
|
389
|
+
return new URL(this.normalizeFilePathForUrl(p), "file:///");
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Determine if a filePath is absolute.
|
|
393
|
+
*
|
|
394
|
+
* @param filePath
|
|
395
|
+
* @returns true if `URL` or `path.isAbsolute(filePath)`
|
|
396
|
+
*/
|
|
397
|
+
isAbsolute(filePath) {
|
|
398
|
+
return isUrlLike(filePath) || this.path.isAbsolute(filePath);
|
|
399
|
+
}
|
|
400
|
+
isUrlLike(url) {
|
|
401
|
+
return isUrlLike(url);
|
|
402
|
+
}
|
|
337
403
|
};
|
|
338
404
|
|
|
339
|
-
|
|
340
|
-
|
|
405
|
+
//#endregion
|
|
406
|
+
//#region src/defaultFileUrlBuilder.mts
|
|
407
|
+
const fileUrlBuilder = new FileUrlBuilder();
|
|
341
408
|
function encodePathChars(filepath) {
|
|
342
|
-
|
|
409
|
+
return fileUrlBuilder.encodePathChars(filepath);
|
|
343
410
|
}
|
|
411
|
+
/**
|
|
412
|
+
* Normalize a file path for use in a URL.
|
|
413
|
+
* ```js
|
|
414
|
+
* const url = new URL(normalizeFilePathForUrl('path\\to\\file.txt'), 'file:///Users/user/');
|
|
415
|
+
* // Result: file:///Users/user/path/to/file.txt
|
|
416
|
+
* ```
|
|
417
|
+
* @param filePath
|
|
418
|
+
* @returns a normalized file path for use as a relative path in a URL.
|
|
419
|
+
*/
|
|
344
420
|
function normalizeFilePathForUrl(filePath) {
|
|
345
|
-
|
|
421
|
+
return fileUrlBuilder.normalizeFilePathForUrl(filePath);
|
|
346
422
|
}
|
|
423
|
+
/**
|
|
424
|
+
* Try to make a file URL.
|
|
425
|
+
* - if filenameOrUrl is already a URL, it is returned as is.
|
|
426
|
+
* -
|
|
427
|
+
* @param filenameOrUrl
|
|
428
|
+
* @param relativeTo - optional URL, if given, filenameOrUrl will be parsed as relative.
|
|
429
|
+
* @returns a URL
|
|
430
|
+
*/
|
|
347
431
|
function toFileURL(filenameOrUrl, relativeTo) {
|
|
348
|
-
|
|
432
|
+
return fileUrlBuilder.toFileURL(filenameOrUrl, relativeTo);
|
|
349
433
|
}
|
|
434
|
+
/**
|
|
435
|
+
* Converts a file path to a URL and adds a trailing slash.
|
|
436
|
+
* @param dir - url to a directory
|
|
437
|
+
* @returns a URL
|
|
438
|
+
*/
|
|
350
439
|
function toFileDirURL(dir) {
|
|
351
|
-
|
|
440
|
+
return fileUrlBuilder.toFileDirURL(dir);
|
|
352
441
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
basenameOfUrlPathname,
|
|
357
|
-
encodePathChars,
|
|
358
|
-
fixUncUrl,
|
|
359
|
-
hasProtocol,
|
|
360
|
-
isDataURL,
|
|
361
|
-
isFileURL,
|
|
362
|
-
isNotUrlLike,
|
|
363
|
-
isURL,
|
|
364
|
-
isUrlLike,
|
|
365
|
-
normalizeFilePathForUrl,
|
|
366
|
-
normalizeWindowsUrl,
|
|
367
|
-
toFileDirURL,
|
|
368
|
-
toFilePathOrHref,
|
|
369
|
-
toFileURL,
|
|
370
|
-
toURL,
|
|
371
|
-
urlBasename,
|
|
372
|
-
urlDirname,
|
|
373
|
-
urlParent,
|
|
374
|
-
urlRelative
|
|
375
|
-
};
|
|
442
|
+
|
|
443
|
+
//#endregion
|
|
444
|
+
export { FileUrlBuilder, addTrailingSlash, basenameOfUrlPathname, encodePathChars, fixUncUrl, hasProtocol, isDataURL, isFileURL, isNotUrlLike, isURL, isUrlLike, normalizeFilePathForUrl, normalizeWindowsUrl, toFileDirURL, toFilePathOrHref, toFileURL, toURL, urlBasename, urlDirname, urlParent, urlRelative };
|
|
376
445
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"access": "public",
|
|
5
5
|
"provenance": true
|
|
6
6
|
},
|
|
7
|
-
"version": "9.0
|
|
7
|
+
"version": "9.1.0",
|
|
8
8
|
"description": "URL parsing and manipulation utilities for cspell",
|
|
9
9
|
"keywords": [
|
|
10
10
|
"cspell",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"!**/*.map"
|
|
35
35
|
],
|
|
36
36
|
"scripts": {
|
|
37
|
-
"build": "
|
|
37
|
+
"build": "tsdown",
|
|
38
38
|
"build:clean": "pnpm clean && pnpm build",
|
|
39
39
|
"clean": "shx rm -rf dist coverage",
|
|
40
40
|
"clean-build": "pnpm build:clean",
|
|
@@ -58,5 +58,5 @@
|
|
|
58
58
|
"engines": {
|
|
59
59
|
"node": ">=20"
|
|
60
60
|
},
|
|
61
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "a7ed42a31debbc86faa4a4ac2c686bdffe5b26b6"
|
|
62
62
|
}
|