@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.
Files changed (3) hide show
  1. package/dist/index.d.ts +210 -182
  2. package/dist/index.js +390 -321
  3. package/package.json +3 -3
package/dist/index.d.ts CHANGED
@@ -1,234 +1,262 @@
1
+ //#region src/dataUrl.d.mts
1
2
  /**
2
- * Try to determine the base name of a URL.
3
- * @param url
4
- * @returns the base name of a URL, including the trailing `/` if present.
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
- * Normalize a file path for use in a URL.
12
- * ```js
13
- * const url = new URL(normalizeFilePathForUrl('path\\to\\file.txt'), 'file:///Users/user/');
14
- * // Result: file:///Users/user/path/to/file.txt
15
- * ```
16
- * @param filePath
17
- * @returns a normalized file path for use as a relative path in a URL.
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
- * Try to make a file URL.
22
- * - if filenameOrUrl is already a URL, it is returned as is.
23
- * -
24
- * @param filenameOrUrl
25
- * @param relativeTo - optional URL, if given, filenameOrUrl will be parsed as relative.
26
- * @returns a URL
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
- * Converts a file path to a URL and adds a trailing slash.
31
- * @param dir - url to a directory
32
- * @returns a URL
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
- * @param url - URL or string to check if it is a file URL.
38
- * @returns true if the URL is a file URL.
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
- * Convert a URL into a string. If it is a file URL, convert it to a path.
43
- * @param url - URL
44
- * @returns path or href
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
- * The root of the path such as '/' or 'c:\'
51
- */
52
- root: string;
53
- /**
54
- * The full directory path such as '/home/user/dir' or 'c:\path\dir'
55
- */
56
- dir: string;
57
- /**
58
- * The file name including extension (if any) such as 'index.html'
59
- */
60
- base: string;
61
- /**
62
- * The file extension (if any) such as '.html'
63
- */
64
- ext: string;
65
- /**
66
- * The file name without extension (if any) such as 'index'
67
- */
68
- name: string;
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
- sep: string;
72
- resolve(...paths: string[]): string;
73
- parse(path: string): ParsedPath;
74
- normalize(path: string): string;
75
- relative(from: string, to: string): string;
76
- isAbsolute(path: string): boolean;
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
- windows?: boolean | undefined;
80
- path?: PathInterface | undefined;
81
- cwd?: URL | undefined;
83
+ windows?: boolean | undefined;
84
+ path?: PathInterface | undefined;
85
+ cwd?: URL | undefined;
82
86
  }
83
87
  declare class FileUrlBuilder {
84
- #private;
85
- private windows;
86
- readonly path: PathInterface;
87
- readonly cwd: URL;
88
- constructor(options?: BuilderOptions);
89
- /**
90
- * Encode special characters in a file path to use in a URL.
91
- * @param filepath
92
- * @returns
93
- */
94
- encodePathChars(filepath: string): string;
95
- /**
96
- * Normalize a file path for use in a URL.
97
- * ```js
98
- * const url = new URL(normalizeFilePathForUrl('path\\to\\file.txt'), 'file:///Users/user/');
99
- * // Result: file:///Users/user/path/to/file.txt
100
- * ```
101
- * @param filePath
102
- * @returns a normalized file path for use as a relative path in a URL.
103
- */
104
- normalizeFilePathForUrl(filePath: string): string;
105
- /**
106
- * Try to make a file URL.
107
- * - if filenameOrUrl is already a URL, it is returned as is.
108
- * @param filenameOrUrl
109
- * @param relativeTo - optional URL, if given, filenameOrUrl will be parsed as relative.
110
- * @returns a URL
111
- */
112
- toFileURL(filenameOrUrl: string | URL, relativeTo?: string | URL): URL;
113
- /**
114
- * Try to make a URL for a directory.
115
- * - if dirOrUrl is already a URL, a slash is appended to the pathname.
116
- * @param dirOrUrl - directory path to convert to a file URL.
117
- * @param relativeTo - optional URL, if given, filenameOrUrl will be parsed as relative.
118
- * @returns a URL
119
- */
120
- toFileDirURL(dirOrUrl: string | URL, relativeTo?: string | URL): URL;
121
- urlToFilePathOrHref(url: URL | string): string;
122
- /**
123
- * Calculate the relative path to go from `urlFrom` to `urlTo`.
124
- * The protocol is not evaluated. Only the `url.pathname` is used.
125
- * The result: `new URL(relative(urlFrom, urlTo), urlFrom).pathname === urlTo.pathname`
126
- * @param urlFrom
127
- * @param urlTo
128
- * @returns the relative path
129
- */
130
- relative(urlFrom: URL, urlTo: URL): string;
131
- /**
132
- * Get the parent directory of a URL.
133
- * @param url
134
- */
135
- urlDirname(url: URL | string): URL;
136
- pathToFileURL(pathname: string, relativeToURL?: URL | string): URL;
137
- rootFileURL(filePath?: string): URL;
138
- /**
139
- * Determine if a filePath is absolute.
140
- *
141
- * @param filePath
142
- * @returns true if `URL` or `path.isAbsolute(filePath)`
143
- */
144
- isAbsolute(filePath: string): boolean;
145
- isUrlLike(url: string | URL): boolean;
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
- * Try to make a URL.
150
- * @param url
151
- * @param relativeTo - optional URL, if given, url will be parsed as relative.
152
- * @returns a URL
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
- * Try to determine the parent directory URL of the uri.
157
- * If it is not a hierarchical URL, then it will return the URL.
158
- * @param url - url to extract the dirname from.
159
- * @returns a URL
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
- * Alias of {@link urlParent}
164
- * Try to determine the parent directory URL of the uri.
165
- * If it is not a hierarchical URL, then it will return the URL.
166
- * @param url - url to extract the dirname from.
167
- * @returns a URL
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
- * return the basename (last portion of the URL pathname) of a path. It does NOT remove the trailing slash.
172
- * @param path - URL pathname to extract the basename from.
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
- * @param filename - filename to check if it is a string containing a URL.
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
- * @param filename - filename to check if it is a string containing a URL or a URL object.
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
- * @param filename - filename to check if it is a string containing a URL.
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
- * @param filename - filename to check if it is a string containing a URL or a URL object.
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
- * Check if `url` is a URL instance.
195
- * @returns
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
- * @param url - url to check
201
- * @param protocol - protocol to check against - e.g. 'file:', 'http:', 'https:'
202
- * @returns
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
- * Attempts to add a trailing slash to the URL pathname if it does not already have one.
207
- * Some If the pathname doesn't start with a `/`, a trailing slash is not added.
208
- * @param url - a URL
209
- * @returns
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
- * Calculate the relative path to go from `urlFrom` to `urlTo`.
214
- * The protocol is not evaluated. Only the `url.pathname` is used.
215
- * @param urlFrom
216
- * @param urlTo
217
- * @returns the relative path
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
- * Ensure that a windows file url is correctly formatted with a capitol letter for the drive.
222
- *
223
- * @param url - URL to check.
224
- * @returns a new URL if modified or converted from a string.
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
- * There is a bug is NodeJS that sometimes causes UNC paths converted to a URL to be prefixed with `file:////`.
229
- * @param url - URL to check.
230
- * @returns fixed URL if needed.
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 { type BuilderOptions, FileUrlBuilder, type PathInterface, addTrailingSlash, basenameOfUrlPathname, encodePathChars, fixUncUrl, hasProtocol, isDataURL, isFileURL, isNotUrlLike, isURL, isUrlLike, normalizeFilePathForUrl, normalizeWindowsUrl, toFileDirURL, toFilePathOrHref, toFileURL, toURL, urlBasename, urlDirname, urlParent, urlRelative };
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
- // src/url.mts
2
- var isURLRegEx = /^(\w[\w-]{1,63}:\/|data:|stdin:)/i;
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
- return normalizeWindowsUrl(url instanceof URL ? url : new URL(url, relativeTo));
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
- url = toURL(url);
8
- if (url.protocol === "data:") {
9
- return url;
10
- }
11
- const hasTrailingSlash = url.pathname.endsWith("/");
12
- if (!url.pathname.startsWith("/")) {
13
- if (!url.pathname) return url;
14
- const parts = url.pathname.split("/").slice(0, hasTrailingSlash ? -2 : -1);
15
- const pathname = parts.join("/") + "/";
16
- return new URL(url.protocol + (url.host ? "//" + url.host : "") + pathname + url.search + url.hash);
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
- var urlDirname = urlParent;
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
- const adj = path.endsWith("/") ? 2 : 0;
23
- const idx = path.lastIndexOf("/", path.length - adj);
24
- return idx >= 0 ? path.slice(idx + 1) : path;
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
- return filename instanceof URL || isURLRegEx.test(filename);
52
+ return filename instanceof URL || isURLRegEx.test(filename);
28
53
  }
29
54
  function isNotUrlLike(filename) {
30
- return !isUrlLike(filename);
55
+ return !isUrlLike(filename);
31
56
  }
57
+ /**
58
+ * Check if `url` is a URL instance.
59
+ * @returns
60
+ */
32
61
  function isURL(url) {
33
- return url instanceof URL;
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
- protocol = protocol.endsWith(":") ? protocol : protocol + ":";
37
- return typeof url === "string" ? url.startsWith(protocol) : url.protocol === protocol;
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
- if (url.pathname.endsWith("/")) return url;
41
- const urlWithSlash = new URL(url.href);
42
- urlWithSlash.pathname += "/";
43
- return urlWithSlash;
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
- return urlToUrlRelative(toURL(urlFrom), toURL(urlTo));
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
- let pFrom = urlFrom.pathname;
50
- const pTo = urlTo.pathname;
51
- if (pFrom === pTo) return "";
52
- pFrom = pFrom.endsWith("/") ? pFrom : new URL("./", urlFrom).pathname;
53
- if (pTo.startsWith(pFrom)) return decodeURIComponent(pTo.slice(pFrom.length));
54
- const p0 = pFrom;
55
- const p1 = pTo;
56
- if (p1.startsWith(p0)) {
57
- return decodeURIComponent(p0 === p1 ? "" : p1.slice(p0.lastIndexOf("/") + 1));
58
- }
59
- const p0Parts = p0.split("/").slice(0, -1);
60
- const p1Parts = p1.split("/");
61
- let i = 0;
62
- for (i = 0; i < p0Parts.length && i < p1Parts.length - 1 && p0Parts[i] === p1Parts[i]; ++i) {
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
- var regExpWindowsPath = /^[\\/]([a-zA-Z]:[\\/])/;
68
- var badUncLocalhostUrl = /^(\/+[a-zA-Z])\$/;
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
- url = typeof url === "string" ? new URL(url) : url;
71
- if (url.protocol === "file:") {
72
- let pathname = url.pathname.replaceAll("%3A", ":").replaceAll("%3a", ":").replaceAll("%24", "$");
73
- if (!url.host) {
74
- pathname = pathname.replace(badUncLocalhostUrl, "$1:");
75
- }
76
- pathname = pathname.replace(regExpWindowsPath, (d) => d.toUpperCase());
77
- if (pathname !== url.pathname) {
78
- url = new URL(url);
79
- url.pathname = pathname;
80
- return fixUncUrl(url);
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
- if (url.href.startsWith("file:////")) {
87
- return new URL(url.href.replace(/^file:\/{4}/, "file://"));
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
- // src/dataUrl.mts
93
- var regMatchFilename = /filename=([^;,]*)/;
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
- function guessDataUrlName(header) {
96
- const filenameMatch = header.match(regMatchFilename);
97
- if (filenameMatch) return filenameMatch[1];
98
- const mime = header.split(";", 1)[0];
99
- return mime.replaceAll(/\W/g, ".");
100
- }
101
- url = toURL(url);
102
- if (url.protocol === "data:") {
103
- return guessDataUrlName(url.pathname.split(",", 1)[0]);
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
- return hasProtocol(url, "data:");
171
+ return hasProtocol(url, "data:");
109
172
  }
110
173
 
111
- // src/FileUrlBuilder.mts
112
- import assert from "node:assert";
113
- import Path from "node:path";
114
- import { pathToFileURL as pathToFileURL2 } from "node:url";
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
- return windowsUrlPathRegExp.test(pathname);
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
- return hasProtocol(url, "file:");
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
- return isFileURL(url) && url.toString().startsWith("file:///") ? toFilePath(url) : url.toString();
194
+ return isFileURL(url) && url.toString().startsWith("file:///") ? toFilePath(url) : url.toString();
128
195
  }
129
196
  function toFilePath(url) {
130
- try {
131
- if (isWindows) {
132
- const u = new URL(url);
133
- if (!isWindowsPathnameWithDriveLatter(u.pathname)) {
134
- const cwdUrl = pathToFileURL(process.cwd());
135
- if (cwdUrl.hostname) {
136
- return fileURLToPath(new URL(u.pathname, cwdUrl));
137
- }
138
- const drive = cwdUrl.pathname.split("/")[1];
139
- u.pathname = `/${drive}${u.pathname}`;
140
- return fileURLToPath(u);
141
- }
142
- }
143
- return pathWindowsDriveLetterToUpper(fileURLToPath(url));
144
- } catch {
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
- var regExpWindowsPathDriveLetter = /^([a-zA-Z]):[\\/]/;
213
+ const regExpWindowsPathDriveLetter = /^([a-zA-Z]):[\\/]/;
149
214
  function pathWindowsDriveLetterToUpper(absoluteFilePath) {
150
- return absoluteFilePath.replace(regExpWindowsPathDriveLetter, (s) => s.toUpperCase());
215
+ return absoluteFilePath.replace(regExpWindowsPathDriveLetter, (s) => s.toUpperCase());
151
216
  }
152
- var regExpWindowsFileUrl = /^file:\/\/\/[a-zA-Z]:\//;
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
- return regExpWindowsFileUrl.test(url.toString());
224
+ return regExpWindowsFileUrl.test(url.toString());
155
225
  }
156
226
 
157
- // src/FileUrlBuilder.mts
158
- var isWindowsPathRegEx = regExpWindowsPathDriveLetter;
159
- var isWindowsPathname = regExpWindowsPath;
160
- var percentRegEx = /%/g;
161
- var backslashRegEx = /\\/g;
162
- var newlineRegEx = /\n/g;
163
- var carriageReturnRegEx = /\r/g;
164
- var tabRegEx = /\t/g;
165
- var questionRegex = /\?/g;
166
- var hashRegex = /#/g;
167
- var ProtocolFile = "file:";
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
- windows;
170
- path;
171
- cwd;
172
- constructor(options = {}) {
173
- const sep = options.path?.sep;
174
- this.windows = options.windows ?? (sep ? sep === "\\" : void 0) ?? isWindows;
175
- this.path = options.path ?? (this.windows ? Path.win32 : Path.posix);
176
- this.cwd = options.cwd ?? this.pathToFileURL(this.path.resolve() + "/", this.rootFileURL());
177
- assert(
178
- this.path.sep === (this.windows ? "\\" : "/"),
179
- `Path separator should match OS type Windows: ${this.windows === true ? "true" : (this.windows ?? "undefined") || "false"}, sep: ${this.path.sep}, options: ` + JSON.stringify({
180
- isWindows,
181
- sep: `${sep}`,
182
- windows: options.windows,
183
- pathSep: options.path?.sep,
184
- n: options.path?.normalize("path/file.txt"),
185
- cwd: options.cwd?.href,
186
- win32: this.path === Path.win32,
187
- posix: this.path === Path.posix,
188
- "win32.normalize": this.path.normalize === Path.win32.normalize,
189
- "posix.normalize": this.path.normalize === Path.posix.normalize
190
- })
191
- );
192
- }
193
- /**
194
- * Encode special characters in a file path to use in a URL.
195
- * @param filepath
196
- * @returns
197
- */
198
- encodePathChars(filepath) {
199
- filepath = filepath.replaceAll(percentRegEx, "%25");
200
- if (!this.windows && !isWindows && filepath.includes("\\")) {
201
- filepath = filepath.replaceAll(backslashRegEx, "%5C");
202
- }
203
- filepath = filepath.replaceAll(newlineRegEx, "%0A");
204
- filepath = filepath.replaceAll(carriageReturnRegEx, "%0D");
205
- filepath = filepath.replaceAll(tabRegEx, "%09");
206
- return filepath;
207
- }
208
- /**
209
- * Normalize a file path for use in a URL.
210
- * ```js
211
- * const url = new URL(normalizeFilePathForUrl('path\\to\\file.txt'), 'file:///Users/user/');
212
- * // Result: file:///Users/user/path/to/file.txt
213
- * ```
214
- * @param filePath
215
- * @returns a normalized file path for use as a relative path in a URL.
216
- */
217
- normalizeFilePathForUrl(filePath) {
218
- filePath = this.encodePathChars(filePath);
219
- filePath = filePath.replaceAll(questionRegex, "%3F");
220
- filePath = filePath.replaceAll(hashRegex, "%23");
221
- const pathname = filePath.replaceAll("\\", "/");
222
- return pathname.replace(isWindowsPathRegEx, (drive) => `/${drive}`.toUpperCase());
223
- }
224
- /**
225
- * Try to make a file URL.
226
- * - if filenameOrUrl is already a URL, it is returned as is.
227
- * @param filenameOrUrl
228
- * @param relativeTo - optional URL, if given, filenameOrUrl will be parsed as relative.
229
- * @returns a URL
230
- */
231
- toFileURL(filenameOrUrl, relativeTo) {
232
- return normalizeWindowsUrl(this.#toFileURL(filenameOrUrl, relativeTo));
233
- }
234
- /**
235
- * Try to make a file URL.
236
- * - if filenameOrUrl is already a URL, it is returned as is.
237
- * @param filenameOrUrl
238
- * @param relativeTo - optional URL, if given, filenameOrUrl will be parsed as relative.
239
- * @returns a URL
240
- */
241
- #toFileURL(filenameOrUrl, relativeTo) {
242
- if (typeof filenameOrUrl !== "string") return filenameOrUrl;
243
- if (isUrlLike(filenameOrUrl)) return normalizeWindowsUrl(new URL(filenameOrUrl));
244
- relativeTo ??= this.cwd;
245
- isWindows && (filenameOrUrl = filenameOrUrl.replaceAll("\\", "/"));
246
- if (this.isAbsolute(filenameOrUrl) && isFileURL(relativeTo)) {
247
- const pathname2 = this.normalizeFilePathForUrl(filenameOrUrl);
248
- if (isWindowsFileUrl(relativeTo) && !isWindowsPathnameWithDriveLatter(pathname2)) {
249
- const relFilePrefix = relativeTo.toString().slice(0, 10);
250
- return normalizeWindowsUrl(new URL(relFilePrefix + pathname2));
251
- }
252
- return normalizeWindowsUrl(new URL("file://" + pathname2));
253
- }
254
- if (isUrlLike(relativeTo)) {
255
- const pathname2 = this.normalizeFilePathForUrl(filenameOrUrl);
256
- return normalizeWindowsUrl(new URL(pathname2, relativeTo));
257
- }
258
- const appendSlash = filenameOrUrl.endsWith("/") ? "/" : "";
259
- const pathname = this.normalizeFilePathForUrl(this.path.resolve(relativeTo.toString(), filenameOrUrl)) + appendSlash;
260
- return normalizeWindowsUrl(new URL("file://" + pathname));
261
- }
262
- /**
263
- * Try to make a URL for a directory.
264
- * - if dirOrUrl is already a URL, a slash is appended to the pathname.
265
- * @param dirOrUrl - directory path to convert to a file URL.
266
- * @param relativeTo - optional URL, if given, filenameOrUrl will be parsed as relative.
267
- * @returns a URL
268
- */
269
- toFileDirURL(dirOrUrl, relativeTo) {
270
- return addTrailingSlash(this.toFileURL(dirOrUrl, relativeTo));
271
- }
272
- urlToFilePathOrHref(url) {
273
- url = this.toFileURL(url);
274
- return this.#urlToFilePathOrHref(url);
275
- }
276
- #urlToFilePathOrHref(url) {
277
- if (url.protocol !== ProtocolFile || url.hostname) return url.href;
278
- const p = this.path === Path ? toFilePathOrHref(url) : decodeURIComponent(url.pathname.split("/").join(this.path.sep));
279
- return pathWindowsDriveLetterToUpper(p.replace(isWindowsPathname, "$1"));
280
- }
281
- /**
282
- * Calculate the relative path to go from `urlFrom` to `urlTo`.
283
- * The protocol is not evaluated. Only the `url.pathname` is used.
284
- * The result: `new URL(relative(urlFrom, urlTo), urlFrom).pathname === urlTo.pathname`
285
- * @param urlFrom
286
- * @param urlTo
287
- * @returns the relative path
288
- */
289
- relative(urlFrom, urlTo) {
290
- if (urlFrom.protocol === urlTo.protocol && urlFrom.protocol === ProtocolFile) {
291
- if (urlFrom.href === urlTo.href) return "";
292
- urlFrom = urlFrom.pathname.endsWith("/") ? urlFrom : new URL("./", urlFrom);
293
- const fromPath = urlFrom.pathname;
294
- const toPath = urlTo.pathname;
295
- if (toPath.startsWith(fromPath)) return decodeURIComponent(toPath.slice(fromPath.length));
296
- const pFrom = this.#urlToFilePathOrHref(urlFrom);
297
- const pTo = this.#urlToFilePathOrHref(urlTo);
298
- const toIsDir = urlTo.pathname.endsWith("/");
299
- let pathname = this.normalizeFilePathForUrl(this.path.relative(pFrom, pTo));
300
- if (toIsDir && !pathname.endsWith("/")) pathname += "/";
301
- return decodeURIComponent(pathname);
302
- }
303
- return decodeURIComponent(urlToUrlRelative(urlFrom, urlTo));
304
- }
305
- /**
306
- * Get the parent directory of a URL.
307
- * @param url
308
- */
309
- urlDirname(url) {
310
- return urlParent(this.toFileURL(url));
311
- }
312
- pathToFileURL(pathname, relativeToURL) {
313
- return new URL(this.normalizeFilePathForUrl(pathname), relativeToURL || this.cwd);
314
- }
315
- rootFileURL(filePath) {
316
- const path = this.path;
317
- const p = path.parse(path.normalize(path.resolve(filePath ?? ".")));
318
- return new URL(this.normalizeFilePathForUrl(p.root), this.#getFsRootURL());
319
- }
320
- #getFsRootURL() {
321
- if (this.path === Path) return pathToFileURL2("/");
322
- const p = this.path.resolve("/");
323
- return new URL(this.normalizeFilePathForUrl(p), "file:///");
324
- }
325
- /**
326
- * Determine if a filePath is absolute.
327
- *
328
- * @param filePath
329
- * @returns true if `URL` or `path.isAbsolute(filePath)`
330
- */
331
- isAbsolute(filePath) {
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
- // src/defaultFileUrlBuilder.mts
340
- var fileUrlBuilder = new FileUrlBuilder();
405
+ //#endregion
406
+ //#region src/defaultFileUrlBuilder.mts
407
+ const fileUrlBuilder = new FileUrlBuilder();
341
408
  function encodePathChars(filepath) {
342
- return fileUrlBuilder.encodePathChars(filepath);
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
- return fileUrlBuilder.normalizeFilePathForUrl(filePath);
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
- return fileUrlBuilder.toFileURL(filenameOrUrl, relativeTo);
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
- return fileUrlBuilder.toFileDirURL(dir);
440
+ return fileUrlBuilder.toFileDirURL(dir);
352
441
  }
353
- export {
354
- FileUrlBuilder,
355
- addTrailingSlash,
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.1",
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": "tsup-node",
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": "bdfabd3686aac9827f3af0ceb4aa74947b5f9d60"
61
+ "gitHead": "a7ed42a31debbc86faa4a4ac2c686bdffe5b26b6"
62
62
  }