@gjsify/url 0.3.13 → 0.3.15

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 (2) hide show
  1. package/lib/esm/index.js +435 -457
  2. package/package.json +4 -4
package/lib/esm/index.js CHANGED
@@ -1,482 +1,460 @@
1
1
  import GLib from "@girs/glib-2.0";
2
+
3
+ //#region src/index.ts
2
4
  const PARSE_FLAGS = GLib.UriFlags.HAS_PASSWORD | GLib.UriFlags.ENCODED | GLib.UriFlags.SCHEME_NORMALIZE;
3
- class URLSearchParams {
4
- _entries = [];
5
- constructor(init) {
6
- if (!init) return;
7
- if (typeof init === "string") {
8
- const s = init.startsWith("?") ? init.slice(1) : init;
9
- if (s) {
10
- for (const pair of s.split("&")) {
11
- const eqIdx = pair.indexOf("=");
12
- if (eqIdx === -1) {
13
- this._entries.push([decodeComponent(pair), ""]);
14
- } else {
15
- this._entries.push([decodeComponent(pair.slice(0, eqIdx)), decodeComponent(pair.slice(eqIdx + 1))]);
16
- }
17
- }
18
- }
19
- } else if (Array.isArray(init)) {
20
- for (const [k, v] of init) {
21
- this._entries.push([String(k), String(v)]);
22
- }
23
- } else if (init instanceof URLSearchParams) {
24
- this._entries = init._entries.map(([k, v]) => [k, v]);
25
- } else {
26
- for (const key of Object.keys(init)) {
27
- this._entries.push([key, String(init[key])]);
28
- }
29
- }
30
- }
31
- get(name) {
32
- for (const [k, v] of this._entries) {
33
- if (k === name) return v;
34
- }
35
- return null;
36
- }
37
- getAll(name) {
38
- return this._entries.filter(([k]) => k === name).map(([, v]) => v);
39
- }
40
- set(name, value) {
41
- let found = false;
42
- this._entries = this._entries.filter(([k]) => {
43
- if (k === name) {
44
- if (!found) {
45
- found = true;
46
- return true;
47
- }
48
- return false;
49
- }
50
- return true;
51
- });
52
- if (found) {
53
- for (let i = 0; i < this._entries.length; i++) {
54
- if (this._entries[i][0] === name) {
55
- this._entries[i][1] = value;
56
- break;
57
- }
58
- }
59
- } else {
60
- this._entries.push([name, value]);
61
- }
62
- }
63
- has(name) {
64
- return this._entries.some(([k]) => k === name);
65
- }
66
- delete(name) {
67
- this._entries = this._entries.filter(([k]) => k !== name);
68
- }
69
- append(name, value) {
70
- this._entries.push([name, value]);
71
- }
72
- sort() {
73
- this._entries.sort((a, b) => {
74
- if (a[0] < b[0]) return -1;
75
- if (a[0] > b[0]) return 1;
76
- return 0;
77
- });
78
- }
79
- toString() {
80
- return this._entries.map(([k, v]) => encodeComponent(k) + "=" + encodeComponent(v)).join("&");
81
- }
82
- forEach(callback) {
83
- for (const [k, v] of this._entries) {
84
- callback(v, k, this);
85
- }
86
- }
87
- *entries() {
88
- yield* this._entries;
89
- }
90
- *keys() {
91
- for (const [k] of this._entries) yield k;
92
- }
93
- *values() {
94
- for (const [, v] of this._entries) yield v;
95
- }
96
- [Symbol.iterator]() {
97
- return this.entries();
98
- }
99
- get size() {
100
- return this._entries.length;
101
- }
102
- }
5
+ var URLSearchParams = class URLSearchParams {
6
+ _entries = [];
7
+ constructor(init) {
8
+ if (!init) return;
9
+ if (typeof init === "string") {
10
+ const s = init.startsWith("?") ? init.slice(1) : init;
11
+ if (s) {
12
+ for (const pair of s.split("&")) {
13
+ const eqIdx = pair.indexOf("=");
14
+ if (eqIdx === -1) {
15
+ this._entries.push([decodeComponent(pair), ""]);
16
+ } else {
17
+ this._entries.push([decodeComponent(pair.slice(0, eqIdx)), decodeComponent(pair.slice(eqIdx + 1))]);
18
+ }
19
+ }
20
+ }
21
+ } else if (Array.isArray(init)) {
22
+ for (const [k, v] of init) {
23
+ this._entries.push([String(k), String(v)]);
24
+ }
25
+ } else if (init instanceof URLSearchParams) {
26
+ this._entries = init._entries.map(([k, v]) => [k, v]);
27
+ } else {
28
+ for (const key of Object.keys(init)) {
29
+ this._entries.push([key, String(init[key])]);
30
+ }
31
+ }
32
+ }
33
+ get(name) {
34
+ for (const [k, v] of this._entries) {
35
+ if (k === name) return v;
36
+ }
37
+ return null;
38
+ }
39
+ getAll(name) {
40
+ return this._entries.filter(([k]) => k === name).map(([, v]) => v);
41
+ }
42
+ set(name, value) {
43
+ let found = false;
44
+ this._entries = this._entries.filter(([k]) => {
45
+ if (k === name) {
46
+ if (!found) {
47
+ found = true;
48
+ return true;
49
+ }
50
+ return false;
51
+ }
52
+ return true;
53
+ });
54
+ if (found) {
55
+ for (let i = 0; i < this._entries.length; i++) {
56
+ if (this._entries[i][0] === name) {
57
+ this._entries[i][1] = value;
58
+ break;
59
+ }
60
+ }
61
+ } else {
62
+ this._entries.push([name, value]);
63
+ }
64
+ }
65
+ has(name) {
66
+ return this._entries.some(([k]) => k === name);
67
+ }
68
+ delete(name) {
69
+ this._entries = this._entries.filter(([k]) => k !== name);
70
+ }
71
+ append(name, value) {
72
+ this._entries.push([name, value]);
73
+ }
74
+ sort() {
75
+ this._entries.sort((a, b) => {
76
+ if (a[0] < b[0]) return -1;
77
+ if (a[0] > b[0]) return 1;
78
+ return 0;
79
+ });
80
+ }
81
+ toString() {
82
+ return this._entries.map(([k, v]) => encodeComponent(k) + "=" + encodeComponent(v)).join("&");
83
+ }
84
+ forEach(callback) {
85
+ for (const [k, v] of this._entries) {
86
+ callback(v, k, this);
87
+ }
88
+ }
89
+ *entries() {
90
+ yield* this._entries;
91
+ }
92
+ *keys() {
93
+ for (const [k] of this._entries) yield k;
94
+ }
95
+ *values() {
96
+ for (const [, v] of this._entries) yield v;
97
+ }
98
+ [Symbol.iterator]() {
99
+ return this.entries();
100
+ }
101
+ get size() {
102
+ return this._entries.length;
103
+ }
104
+ };
103
105
  function decodeComponent(s) {
104
- try {
105
- return decodeURIComponent(s.replace(/\+/g, " "));
106
- } catch {
107
- return s;
108
- }
106
+ try {
107
+ return decodeURIComponent(s.replace(/\+/g, " "));
108
+ } catch {
109
+ return s;
110
+ }
109
111
  }
110
112
  function encodeComponent(s) {
111
- return encodeURIComponent(s).replace(/%20/g, "+");
112
- }
113
- class URL {
114
- #uri;
115
- // GLib.Uri
116
- #searchParams;
117
- constructor(url, base) {
118
- const urlStr = url instanceof URL ? url.href : String(url);
119
- try {
120
- if (base !== void 0) {
121
- const baseStr = base instanceof URL ? base.href : String(base);
122
- const baseUri = GLib.Uri.parse(baseStr, PARSE_FLAGS);
123
- this.#uri = baseUri.parse_relative(urlStr, PARSE_FLAGS);
124
- } else {
125
- this.#uri = GLib.Uri.parse(urlStr, PARSE_FLAGS);
126
- }
127
- } catch (e) {
128
- throw new TypeError(`Invalid URL: ${urlStr}`);
129
- }
130
- if (!this.#uri) {
131
- throw new TypeError(`Invalid URL: ${urlStr}`);
132
- }
133
- this.#searchParams = new URLSearchParams(this.#uri.get_query() || "");
134
- }
135
- get protocol() {
136
- return this.#uri.get_scheme() + ":";
137
- }
138
- get hostname() {
139
- return (this.#uri.get_host() || "").toLowerCase();
140
- }
141
- get port() {
142
- const p = this.#uri.get_port();
143
- if (p === -1) return "";
144
- const scheme = this.#uri.get_scheme();
145
- if ((scheme === "http" || scheme === "ws") && p === 80) return "";
146
- if ((scheme === "https" || scheme === "wss") && p === 443) return "";
147
- if (scheme === "ftp" && p === 21) return "";
148
- return String(p);
149
- }
150
- get host() {
151
- const hostname = this.hostname;
152
- const port = this.port;
153
- return port ? `${hostname}:${port}` : hostname;
154
- }
155
- get pathname() {
156
- return this.#uri.get_path() || "/";
157
- }
158
- get search() {
159
- const q = this.#uri.get_query();
160
- return q ? "?" + q : "";
161
- }
162
- get hash() {
163
- const f = this.#uri.get_fragment();
164
- return f ? "#" + f : "";
165
- }
166
- get origin() {
167
- const p = this.protocol;
168
- if (p === "http:" || p === "https:" || p === "ftp:") {
169
- return `${p}//${this.host}`;
170
- }
171
- return "null";
172
- }
173
- get username() {
174
- return this.#uri.get_user() || "";
175
- }
176
- get password() {
177
- return this.#uri.get_password() || "";
178
- }
179
- get href() {
180
- let result = this.protocol;
181
- const scheme = this.#uri.get_scheme();
182
- const isSpecial = scheme === "http" || scheme === "https" || scheme === "ftp" || scheme === "file" || scheme === "ws" || scheme === "wss";
183
- if (isSpecial || this.hostname) {
184
- result += "//";
185
- }
186
- const user = this.username;
187
- const pass = this.password;
188
- if (user) {
189
- result += user;
190
- if (pass) result += ":" + pass;
191
- result += "@";
192
- }
193
- result += this.hostname;
194
- if (this.port) result += ":" + this.port;
195
- const pathname = this.pathname;
196
- result += pathname;
197
- result += this.search;
198
- result += this.hash;
199
- return result;
200
- }
201
- get searchParams() {
202
- return this.#searchParams;
203
- }
204
- toString() {
205
- return this.href;
206
- }
207
- toJSON() {
208
- return this.href;
209
- }
210
- // ---- URL.createObjectURL / URL.revokeObjectURL ----
211
- //
212
- // Consumers like Excalibur.js do `const src = URL.createObjectURL(blob);
213
- // image.src = src;`. For that to work on GJS we need `src` to be a path
214
- // `HTMLImageElement` / `HTMLAudioElement` / `FontFace` can actually read —
215
- // i.e. a `file://` URL. We implement this as a static method on our own
216
- // URL class (no globalThis monkey-patching):
217
- //
218
- // - Fast path: if the Blob already carries a `_tmpPath` (e.g. written
219
- // by `@gjsify/fetch` XHR when `responseType='blob'`), wrap it as
220
- // `file://<_tmpPath>`.
221
- // - Slow path: if the Blob has `arrayBuffer()`/bytes but no `_tmpPath`,
222
- // materialise the bytes into a GLib temp file and wrap that. This
223
- // path is async in the spec — but W3C `createObjectURL` is sync. We
224
- // read the bytes via `GLib.Bytes`-style synchronous access when
225
- // possible and fall back to a sentinel if not.
226
- //
227
- // Reference: https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL
228
- static _objectURLPaths = /* @__PURE__ */ new Map();
229
- static _objectURLCounter = 0;
230
- static createObjectURL(blob) {
231
- const tmp = blob?._tmpPath;
232
- if (typeof tmp === "string" && tmp.length > 0) {
233
- const url = `file://${tmp}`;
234
- URL._objectURLPaths.set(url, tmp);
235
- return url;
236
- }
237
- return "file:///dev/null";
238
- }
239
- static revokeObjectURL(url) {
240
- const path = URL._objectURLPaths.get(url);
241
- if (!path) return;
242
- try {
243
- GLib.unlink(path);
244
- } catch {
245
- }
246
- URL._objectURLPaths.delete(url);
247
- }
113
+ return encodeURIComponent(s).replace(/%20/g, "+");
248
114
  }
115
+ var URL = class URL {
116
+ #uri;
117
+ #searchParams;
118
+ constructor(url, base) {
119
+ const urlStr = url instanceof URL ? url.href : String(url);
120
+ try {
121
+ if (base !== undefined) {
122
+ const baseStr = base instanceof URL ? base.href : String(base);
123
+ const baseUri = GLib.Uri.parse(baseStr, PARSE_FLAGS);
124
+ this.#uri = baseUri.parse_relative(urlStr, PARSE_FLAGS);
125
+ } else {
126
+ this.#uri = GLib.Uri.parse(urlStr, PARSE_FLAGS);
127
+ }
128
+ } catch (e) {
129
+ throw new TypeError(`Invalid URL: ${urlStr}`);
130
+ }
131
+ if (!this.#uri) {
132
+ throw new TypeError(`Invalid URL: ${urlStr}`);
133
+ }
134
+ this.#searchParams = new URLSearchParams(this.#uri.get_query() || "");
135
+ }
136
+ get protocol() {
137
+ return this.#uri.get_scheme() + ":";
138
+ }
139
+ get hostname() {
140
+ return (this.#uri.get_host() || "").toLowerCase();
141
+ }
142
+ get port() {
143
+ const p = this.#uri.get_port();
144
+ if (p === -1) return "";
145
+ const scheme = this.#uri.get_scheme();
146
+ if ((scheme === "http" || scheme === "ws") && p === 80) return "";
147
+ if ((scheme === "https" || scheme === "wss") && p === 443) return "";
148
+ if (scheme === "ftp" && p === 21) return "";
149
+ return String(p);
150
+ }
151
+ get host() {
152
+ const hostname = this.hostname;
153
+ const port = this.port;
154
+ return port ? `${hostname}:${port}` : hostname;
155
+ }
156
+ get pathname() {
157
+ return this.#uri.get_path() || "/";
158
+ }
159
+ get search() {
160
+ const q = this.#uri.get_query();
161
+ return q ? "?" + q : "";
162
+ }
163
+ get hash() {
164
+ const f = this.#uri.get_fragment();
165
+ return f ? "#" + f : "";
166
+ }
167
+ get origin() {
168
+ const p = this.protocol;
169
+ if (p === "http:" || p === "https:" || p === "ftp:") {
170
+ return `${p}//${this.host}`;
171
+ }
172
+ return "null";
173
+ }
174
+ get username() {
175
+ return this.#uri.get_user() || "";
176
+ }
177
+ get password() {
178
+ return this.#uri.get_password() || "";
179
+ }
180
+ get href() {
181
+ let result = this.protocol;
182
+ const scheme = this.#uri.get_scheme();
183
+ const isSpecial = scheme === "http" || scheme === "https" || scheme === "ftp" || scheme === "file" || scheme === "ws" || scheme === "wss";
184
+ if (isSpecial || this.hostname) {
185
+ result += "//";
186
+ }
187
+ const user = this.username;
188
+ const pass = this.password;
189
+ if (user) {
190
+ result += user;
191
+ if (pass) result += ":" + pass;
192
+ result += "@";
193
+ }
194
+ result += this.hostname;
195
+ if (this.port) result += ":" + this.port;
196
+ const pathname = this.pathname;
197
+ result += pathname;
198
+ result += this.search;
199
+ result += this.hash;
200
+ return result;
201
+ }
202
+ get searchParams() {
203
+ return this.#searchParams;
204
+ }
205
+ toString() {
206
+ return this.href;
207
+ }
208
+ toJSON() {
209
+ return this.href;
210
+ }
211
+ static _objectURLPaths = new Map();
212
+ static _objectURLCounter = 0;
213
+ static createObjectURL(blob) {
214
+ const tmp = blob?._tmpPath;
215
+ if (typeof tmp === "string" && tmp.length > 0) {
216
+ const url = `file://${tmp}`;
217
+ URL._objectURLPaths.set(url, tmp);
218
+ return url;
219
+ }
220
+ return "file:///dev/null";
221
+ }
222
+ static revokeObjectURL(url) {
223
+ const path = URL._objectURLPaths.get(url);
224
+ if (!path) return;
225
+ try {
226
+ GLib.unlink(path);
227
+ } catch {}
228
+ URL._objectURLPaths.delete(url);
229
+ }
230
+ };
249
231
  function parse(urlString, parseQueryString, slashesDenoteHost) {
250
- if (typeof urlString !== "string") {
251
- throw new TypeError('The "url" argument must be of type string. Received type ' + typeof urlString);
252
- }
253
- const result = {
254
- protocol: null,
255
- slashes: null,
256
- auth: null,
257
- host: null,
258
- port: null,
259
- hostname: null,
260
- hash: null,
261
- search: null,
262
- query: null,
263
- pathname: null,
264
- path: null,
265
- href: urlString
266
- };
267
- let rest = urlString.trim();
268
- const hashIdx = rest.indexOf("#");
269
- if (hashIdx !== -1) {
270
- result.hash = rest.slice(hashIdx);
271
- rest = rest.slice(0, hashIdx);
272
- }
273
- const qIdx = rest.indexOf("?");
274
- if (qIdx !== -1) {
275
- result.search = rest.slice(qIdx);
276
- result.query = parseQueryString ? Object.fromEntries(new URLSearchParams(rest.slice(qIdx + 1))) : rest.slice(qIdx + 1);
277
- rest = rest.slice(0, qIdx);
278
- }
279
- const protoMatch = /^([a-z][a-z0-9.+-]*:)/i.exec(rest);
280
- if (protoMatch) {
281
- result.protocol = protoMatch[1].toLowerCase();
282
- rest = rest.slice(result.protocol.length);
283
- }
284
- if (slashesDenoteHost || result.protocol) {
285
- const hasSlashes = rest.startsWith("//");
286
- if (hasSlashes) {
287
- result.slashes = true;
288
- rest = rest.slice(2);
289
- }
290
- }
291
- if (result.slashes || result.protocol && !["javascript:", "data:", "mailto:"].includes(result.protocol)) {
292
- let hostEnd = -1;
293
- for (let i = 0; i < rest.length; i++) {
294
- const ch = rest[i];
295
- if (ch === "/" || ch === "\\") {
296
- hostEnd = i;
297
- break;
298
- }
299
- }
300
- const hostPart = hostEnd === -1 ? rest : rest.slice(0, hostEnd);
301
- rest = hostEnd === -1 ? "" : rest.slice(hostEnd);
302
- const atIdx = hostPart.lastIndexOf("@");
303
- if (atIdx !== -1) {
304
- result.auth = decodeURIComponent(hostPart.slice(0, atIdx));
305
- const hostWithPort = hostPart.slice(atIdx + 1);
306
- parseHostPort(hostWithPort, result);
307
- } else {
308
- parseHostPort(hostPart, result);
309
- }
310
- }
311
- result.pathname = rest || (result.slashes ? "/" : null);
312
- if (result.pathname !== null || result.search !== null) {
313
- result.path = (result.pathname || "") + (result.search || "");
314
- }
315
- result.href = format(result);
316
- return result;
232
+ if (typeof urlString !== "string") {
233
+ throw new TypeError("The \"url\" argument must be of type string. Received type " + typeof urlString);
234
+ }
235
+ const result = {
236
+ protocol: null,
237
+ slashes: null,
238
+ auth: null,
239
+ host: null,
240
+ port: null,
241
+ hostname: null,
242
+ hash: null,
243
+ search: null,
244
+ query: null,
245
+ pathname: null,
246
+ path: null,
247
+ href: urlString
248
+ };
249
+ let rest = urlString.trim();
250
+ const hashIdx = rest.indexOf("#");
251
+ if (hashIdx !== -1) {
252
+ result.hash = rest.slice(hashIdx);
253
+ rest = rest.slice(0, hashIdx);
254
+ }
255
+ const qIdx = rest.indexOf("?");
256
+ if (qIdx !== -1) {
257
+ result.search = rest.slice(qIdx);
258
+ result.query = parseQueryString ? Object.fromEntries(new URLSearchParams(rest.slice(qIdx + 1))) : rest.slice(qIdx + 1);
259
+ rest = rest.slice(0, qIdx);
260
+ }
261
+ const protoMatch = /^([a-z][a-z0-9.+-]*:)/i.exec(rest);
262
+ if (protoMatch) {
263
+ result.protocol = protoMatch[1].toLowerCase();
264
+ rest = rest.slice(result.protocol.length);
265
+ }
266
+ if (slashesDenoteHost || result.protocol) {
267
+ const hasSlashes = rest.startsWith("//");
268
+ if (hasSlashes) {
269
+ result.slashes = true;
270
+ rest = rest.slice(2);
271
+ }
272
+ }
273
+ if (result.slashes || result.protocol && ![
274
+ "javascript:",
275
+ "data:",
276
+ "mailto:"
277
+ ].includes(result.protocol)) {
278
+ let hostEnd = -1;
279
+ for (let i = 0; i < rest.length; i++) {
280
+ const ch = rest[i];
281
+ if (ch === "/" || ch === "\\") {
282
+ hostEnd = i;
283
+ break;
284
+ }
285
+ }
286
+ const hostPart = hostEnd === -1 ? rest : rest.slice(0, hostEnd);
287
+ rest = hostEnd === -1 ? "" : rest.slice(hostEnd);
288
+ const atIdx = hostPart.lastIndexOf("@");
289
+ if (atIdx !== -1) {
290
+ result.auth = decodeURIComponent(hostPart.slice(0, atIdx));
291
+ const hostWithPort = hostPart.slice(atIdx + 1);
292
+ parseHostPort(hostWithPort, result);
293
+ } else {
294
+ parseHostPort(hostPart, result);
295
+ }
296
+ }
297
+ result.pathname = rest || (result.slashes ? "/" : null);
298
+ if (result.pathname !== null || result.search !== null) {
299
+ result.path = (result.pathname || "") + (result.search || "");
300
+ }
301
+ result.href = format(result);
302
+ return result;
317
303
  }
318
304
  function parseHostPort(hostPart, result) {
319
- if (!hostPart) return;
320
- const bracketIdx = hostPart.indexOf("[");
321
- if (bracketIdx !== -1) {
322
- const bracketEnd = hostPart.indexOf("]", bracketIdx);
323
- if (bracketEnd !== -1) {
324
- const portStr = hostPart.slice(bracketEnd + 1);
325
- if (portStr.startsWith(":")) {
326
- result.port = portStr.slice(1);
327
- }
328
- result.hostname = hostPart.slice(bracketIdx, bracketEnd + 1);
329
- result.host = result.hostname + (result.port ? ":" + result.port : "");
330
- return;
331
- }
332
- }
333
- const colonIdx = hostPart.lastIndexOf(":");
334
- if (colonIdx !== -1) {
335
- const portCandidate = hostPart.slice(colonIdx + 1);
336
- if (/^\d*$/.test(portCandidate)) {
337
- result.port = portCandidate || null;
338
- result.hostname = hostPart.slice(0, colonIdx).toLowerCase();
339
- } else {
340
- result.hostname = hostPart.toLowerCase();
341
- }
342
- } else {
343
- result.hostname = hostPart.toLowerCase();
344
- }
345
- result.host = result.hostname + (result.port ? ":" + result.port : "");
305
+ if (!hostPart) return;
306
+ const bracketIdx = hostPart.indexOf("[");
307
+ if (bracketIdx !== -1) {
308
+ const bracketEnd = hostPart.indexOf("]", bracketIdx);
309
+ if (bracketEnd !== -1) {
310
+ const portStr = hostPart.slice(bracketEnd + 1);
311
+ if (portStr.startsWith(":")) {
312
+ result.port = portStr.slice(1);
313
+ }
314
+ result.hostname = hostPart.slice(bracketIdx, bracketEnd + 1);
315
+ result.host = result.hostname + (result.port ? ":" + result.port : "");
316
+ return;
317
+ }
318
+ }
319
+ const colonIdx = hostPart.lastIndexOf(":");
320
+ if (colonIdx !== -1) {
321
+ const portCandidate = hostPart.slice(colonIdx + 1);
322
+ if (/^\d*$/.test(portCandidate)) {
323
+ result.port = portCandidate || null;
324
+ result.hostname = hostPart.slice(0, colonIdx).toLowerCase();
325
+ } else {
326
+ result.hostname = hostPart.toLowerCase();
327
+ }
328
+ } else {
329
+ result.hostname = hostPart.toLowerCase();
330
+ }
331
+ result.host = result.hostname + (result.port ? ":" + result.port : "");
346
332
  }
347
333
  function format(urlObject) {
348
- if (typeof urlObject === "string") {
349
- return urlObject;
350
- }
351
- if (urlObject instanceof URL) {
352
- return urlObject.href;
353
- }
354
- const obj = urlObject;
355
- let result = "";
356
- if (obj.protocol) {
357
- result += obj.protocol;
358
- }
359
- if (obj.slashes || obj.protocol && !["javascript:", "data:", "mailto:"].includes(obj.protocol || "")) {
360
- result += "//";
361
- }
362
- if (obj.auth) {
363
- result += encodeURIComponent(obj.auth) + "@";
364
- }
365
- if (obj.host) {
366
- result += obj.host;
367
- } else {
368
- if (obj.hostname) {
369
- result += obj.hostname;
370
- }
371
- if (obj.port) {
372
- result += ":" + obj.port;
373
- }
374
- }
375
- if (obj.pathname) {
376
- result += obj.pathname;
377
- }
378
- if (obj.search) {
379
- result += obj.search;
380
- } else if (obj.query && typeof obj.query === "object") {
381
- const qs = new URLSearchParams(obj.query).toString();
382
- if (qs) result += "?" + qs;
383
- }
384
- if (obj.hash) {
385
- result += obj.hash;
386
- }
387
- return result;
334
+ if (typeof urlObject === "string") {
335
+ return urlObject;
336
+ }
337
+ if (urlObject instanceof URL) {
338
+ return urlObject.href;
339
+ }
340
+ const obj = urlObject;
341
+ let result = "";
342
+ if (obj.protocol) {
343
+ result += obj.protocol;
344
+ }
345
+ if (obj.slashes || obj.protocol && ![
346
+ "javascript:",
347
+ "data:",
348
+ "mailto:"
349
+ ].includes(obj.protocol || "")) {
350
+ result += "//";
351
+ }
352
+ if (obj.auth) {
353
+ result += encodeURIComponent(obj.auth) + "@";
354
+ }
355
+ if (obj.host) {
356
+ result += obj.host;
357
+ } else {
358
+ if (obj.hostname) {
359
+ result += obj.hostname;
360
+ }
361
+ if (obj.port) {
362
+ result += ":" + obj.port;
363
+ }
364
+ }
365
+ if (obj.pathname) {
366
+ result += obj.pathname;
367
+ }
368
+ if (obj.search) {
369
+ result += obj.search;
370
+ } else if (obj.query && typeof obj.query === "object") {
371
+ const qs = new URLSearchParams(obj.query).toString();
372
+ if (qs) result += "?" + qs;
373
+ }
374
+ if (obj.hash) {
375
+ result += obj.hash;
376
+ }
377
+ return result;
388
378
  }
389
379
  function resolve(from, to) {
390
- return new URL(to, new URL(from, "resolve://")).href.replace(/^resolve:\/\//, "");
380
+ return new URL(to, new URL(from, "resolve://")).href.replace(/^resolve:\/\//, "");
391
381
  }
392
382
  function fileURLToPath(url) {
393
- if (typeof url === "string") {
394
- url = new URL(url);
395
- }
396
- if (!(url instanceof URL)) {
397
- throw new TypeError('The "url" argument must be of type string or URL. Received type ' + typeof url);
398
- }
399
- if (url.protocol !== "file:") {
400
- throw new TypeError("The URL must be of scheme file");
401
- }
402
- if (url.hostname !== "" && url.hostname !== "localhost") {
403
- throw new TypeError(
404
- `File URL host must be "localhost" or empty on linux`
405
- );
406
- }
407
- const pathname = url.pathname;
408
- for (let i = 0; i < pathname.length; i++) {
409
- if (pathname[i] === "%") {
410
- const third = pathname.codePointAt(i + 2) | 32;
411
- if (pathname[i + 1] === "2" && third === 102) {
412
- throw new TypeError("File URL path must not include encoded / characters");
413
- }
414
- }
415
- }
416
- return decodeURIComponent(pathname);
383
+ if (typeof url === "string") {
384
+ url = new URL(url);
385
+ }
386
+ if (!(url instanceof URL)) {
387
+ throw new TypeError("The \"url\" argument must be of type string or URL. Received type " + typeof url);
388
+ }
389
+ if (url.protocol !== "file:") {
390
+ throw new TypeError("The URL must be of scheme file");
391
+ }
392
+ if (url.hostname !== "" && url.hostname !== "localhost") {
393
+ throw new TypeError(`File URL host must be "localhost" or empty on linux`);
394
+ }
395
+ const pathname = url.pathname;
396
+ for (let i = 0; i < pathname.length; i++) {
397
+ if (pathname[i] === "%") {
398
+ const third = pathname.codePointAt(i + 2) | 32;
399
+ if (pathname[i + 1] === "2" && third === 102) {
400
+ throw new TypeError("File URL path must not include encoded / characters");
401
+ }
402
+ }
403
+ }
404
+ return decodeURIComponent(pathname);
417
405
  }
418
406
  function pathToFileURL(filepath) {
419
- let resolved = filepath;
420
- if (filepath[0] !== "/") {
421
- if (typeof globalThis.process?.cwd === "function") {
422
- resolved = globalThis.process.cwd() + "/" + filepath;
423
- } else {
424
- try {
425
- if (GLib?.get_current_dir) {
426
- resolved = GLib.get_current_dir() + "/" + filepath;
427
- }
428
- } catch {
429
- }
430
- }
431
- }
432
- return new URL("file://" + encodePathForURL(resolved));
407
+ let resolved = filepath;
408
+ if (filepath[0] !== "/") {
409
+ if (typeof globalThis.process?.cwd === "function") {
410
+ resolved = globalThis.process.cwd() + "/" + filepath;
411
+ } else {
412
+ try {
413
+ if (GLib?.get_current_dir) {
414
+ resolved = GLib.get_current_dir() + "/" + filepath;
415
+ }
416
+ } catch {}
417
+ }
418
+ }
419
+ return new URL("file://" + encodePathForURL(resolved));
433
420
  }
434
421
  function encodePathForURL(filepath) {
435
- let result = "";
436
- for (let i = 0; i < filepath.length; i++) {
437
- const ch = filepath[i];
438
- if (ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch >= "0" && ch <= "9" || ch === "/" || ch === "-" || ch === "_" || ch === "." || ch === "~" || ch === ":" || ch === "@" || ch === "!") {
439
- result += ch;
440
- } else {
441
- result += encodeURIComponent(ch);
442
- }
443
- }
444
- return result;
422
+ let result = "";
423
+ for (let i = 0; i < filepath.length; i++) {
424
+ const ch = filepath[i];
425
+ if (ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch >= "0" && ch <= "9" || ch === "/" || ch === "-" || ch === "_" || ch === "." || ch === "~" || ch === ":" || ch === "@" || ch === "!") {
426
+ result += ch;
427
+ } else {
428
+ result += encodeURIComponent(ch);
429
+ }
430
+ }
431
+ return result;
445
432
  }
446
433
  function domainToASCII(domain) {
447
- try {
448
- return new URL(`http://${domain}`).hostname;
449
- } catch {
450
- return "";
451
- }
434
+ try {
435
+ return new URL(`http://${domain}`).hostname;
436
+ } catch {
437
+ return "";
438
+ }
452
439
  }
453
440
  function domainToUnicode(domain) {
454
- try {
455
- return new URL(`http://${domain}`).hostname;
456
- } catch {
457
- return "";
458
- }
441
+ try {
442
+ return new URL(`http://${domain}`).hostname;
443
+ } catch {
444
+ return "";
445
+ }
459
446
  }
460
- var index_default = {
461
- URL,
462
- URLSearchParams,
463
- parse,
464
- format,
465
- resolve,
466
- fileURLToPath,
467
- pathToFileURL,
468
- domainToASCII,
469
- domainToUnicode
470
- };
471
- export {
472
- URL,
473
- URLSearchParams,
474
- index_default as default,
475
- domainToASCII,
476
- domainToUnicode,
477
- fileURLToPath,
478
- format,
479
- parse,
480
- pathToFileURL,
481
- resolve
447
+ var src_default = {
448
+ URL,
449
+ URLSearchParams,
450
+ parse,
451
+ format,
452
+ resolve,
453
+ fileURLToPath,
454
+ pathToFileURL,
455
+ domainToASCII,
456
+ domainToUnicode
482
457
  };
458
+
459
+ //#endregion
460
+ export { URL, URLSearchParams, src_default as default, domainToASCII, domainToUnicode, fileURLToPath, format, parse, pathToFileURL, resolve };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/url",
3
- "version": "0.3.13",
3
+ "version": "0.3.15",
4
4
  "description": "Node.js url module for Gjs",
5
5
  "type": "module",
6
6
  "module": "lib/esm/index.js",
@@ -30,11 +30,11 @@
30
30
  "fs"
31
31
  ],
32
32
  "dependencies": {
33
- "@girs/glib-2.0": "^2.88.0-4.0.0-rc.9"
33
+ "@girs/glib-2.0": "2.88.0-4.0.0-rc.9"
34
34
  },
35
35
  "devDependencies": {
36
- "@gjsify/cli": "^0.3.13",
37
- "@gjsify/unit": "^0.3.13",
36
+ "@gjsify/cli": "^0.3.15",
37
+ "@gjsify/unit": "^0.3.15",
38
38
  "@types/node": "^25.6.0",
39
39
  "typescript": "^6.0.3"
40
40
  }