@jeniex/utils 1.0.6 → 1.0.8
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/browser/index.cjs +180 -2
- package/browser/index.d.ts +53 -3
- package/browser/index.js +172 -3
- package/package.json +1 -1
package/browser/index.cjs
CHANGED
|
@@ -50,9 +50,9 @@ else {
|
|
|
50
50
|
infoObject = { script: { name: document.title } };
|
|
51
51
|
}
|
|
52
52
|
const scriptName = infoObject.script.name;
|
|
53
|
-
/** The identifier of the script to be used in logging */
|
|
53
|
+
/** The identifier of the script to be used in logging. */
|
|
54
54
|
const logId = `[${scriptName}]:`;
|
|
55
|
-
/** The initial tab URL on the script run */
|
|
55
|
+
/** The initial tab URL on the script run. */
|
|
56
56
|
const tabURL = window.location.href;
|
|
57
57
|
|
|
58
58
|
function alert(message) {
|
|
@@ -69,6 +69,90 @@ function prompt(message, _default) {
|
|
|
69
69
|
return window.prompt(`[ ${scriptName} ]\n\n${message}`, _default);
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
async function fishResponse(url, options) {
|
|
73
|
+
const response = await fetch(url, options);
|
|
74
|
+
if (!response.ok) {
|
|
75
|
+
throw new Error(`Request to ${response.url} ended with ${response.status} status.`);
|
|
76
|
+
}
|
|
77
|
+
return response;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Note: to set the 'cookie' header, you have to set 'anonymous' to true.
|
|
81
|
+
async function fishXResponse(url, fishOptions) {
|
|
82
|
+
const { method, anonymous, headers, body, timeOut, onProgress } = fishOptions ?? {};
|
|
83
|
+
return new Promise((resolve, reject) => {
|
|
84
|
+
GM.xmlHttpRequest({
|
|
85
|
+
url,
|
|
86
|
+
method: method ?? 'GET',
|
|
87
|
+
headers,
|
|
88
|
+
anonymous,
|
|
89
|
+
data: body,
|
|
90
|
+
responseType: 'blob',
|
|
91
|
+
timeout: timeOut,
|
|
92
|
+
onprogress: onProgress,
|
|
93
|
+
onload({ response, statusText, status, finalUrl }) {
|
|
94
|
+
const ok = status >= 200 && status < 300;
|
|
95
|
+
if (!ok) {
|
|
96
|
+
reject(new Error(`Request to ${url} ended with ${status} status.`));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const properResponse = new Response(response, {
|
|
100
|
+
statusText,
|
|
101
|
+
status,
|
|
102
|
+
});
|
|
103
|
+
Object.defineProperty(properResponse, 'url', { value: finalUrl });
|
|
104
|
+
resolve(properResponse);
|
|
105
|
+
},
|
|
106
|
+
onerror({ status }) {
|
|
107
|
+
reject(new Error(`Request to ${url} ended with ${status} status.`));
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async function fishBlob(url, options, x) {
|
|
114
|
+
const response = await (x ? fishXResponse : fishResponse)(url, options);
|
|
115
|
+
return response.blob();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function fishBuffer(url, options, x) {
|
|
119
|
+
const response = await (x ? fishXResponse : fishResponse)(url, options);
|
|
120
|
+
return response.arrayBuffer();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async function fishDocument(url, options, x) {
|
|
124
|
+
const response = await (x ? fishXResponse : fishResponse)(url, options);
|
|
125
|
+
const responseText = await response.text();
|
|
126
|
+
const parser = new DOMParser();
|
|
127
|
+
return parser.parseFromString(responseText, 'text/html');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async function fishJson(url, options, x) {
|
|
131
|
+
const response = await (x ? fishXResponse : fishResponse)(url, options);
|
|
132
|
+
return response.json();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async function fishText(url, options, x) {
|
|
136
|
+
const response = await (x ? fishXResponse : fishResponse)(url, options);
|
|
137
|
+
return response.text();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// https://httpbin.org/anything
|
|
141
|
+
const fish = {
|
|
142
|
+
blob: async (url, options) => fishBlob(url, options),
|
|
143
|
+
buffer: async (url, options) => fishBuffer(url, options),
|
|
144
|
+
document: async (url, options) => fishDocument(url, options),
|
|
145
|
+
json: async (url, options) => fishJson(url, options),
|
|
146
|
+
text: async (url, options) => fishText(url, options),
|
|
147
|
+
};
|
|
148
|
+
const fishX = {
|
|
149
|
+
blob: async (url, options) => fishBlob(url, options, true),
|
|
150
|
+
buffer: async (url, options) => fishBuffer(url, options, true),
|
|
151
|
+
document: async (url, options) => fishDocument(url, options, true),
|
|
152
|
+
json: async (url, options) => fishJson(url, options, true),
|
|
153
|
+
text: async (url, options) => fishText(url, options, true),
|
|
154
|
+
};
|
|
155
|
+
|
|
72
156
|
function $(selectors, parent) {
|
|
73
157
|
const element = (parent ?? document).querySelector(ensureJoin(selectors));
|
|
74
158
|
if (element === null) {
|
|
@@ -84,6 +168,91 @@ function $$(selectors, parent) {
|
|
|
84
168
|
return elements;
|
|
85
169
|
}
|
|
86
170
|
|
|
171
|
+
/**
|
|
172
|
+
* @param key The name of the param in the search query.
|
|
173
|
+
* @param fullURL If provided, it will be our target, otherwise it is the current location.
|
|
174
|
+
*/
|
|
175
|
+
function getSearchParam(key, fullURL) {
|
|
176
|
+
const { search } = new URL(fullURL ?? window.location.href);
|
|
177
|
+
const searchParams = new URLSearchParams(search);
|
|
178
|
+
const value = searchParams.get(key);
|
|
179
|
+
if (value === null) {
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
return value;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
*
|
|
186
|
+
* @param key The name of the param that is to be in the search query.
|
|
187
|
+
* @param value Its value.
|
|
188
|
+
* @param fullURL If provided, it will be our target, otherwise it is the current location.
|
|
189
|
+
*/
|
|
190
|
+
function setSearchParam(key, value, fullURL) {
|
|
191
|
+
const updatedURL = [];
|
|
192
|
+
const { origin, pathname, search, hash } = new URL(fullURL ?? window.location.href);
|
|
193
|
+
const searchParams = new URLSearchParams(search);
|
|
194
|
+
searchParams.set(key, value);
|
|
195
|
+
updatedURL.push(origin, pathname, '?', searchParams.toString());
|
|
196
|
+
if (hash !== '') {
|
|
197
|
+
updatedURL.push(hash);
|
|
198
|
+
}
|
|
199
|
+
return updatedURL.join('');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function addStyle(css, parent = document.documentElement) {
|
|
203
|
+
const style = document.createElement('style');
|
|
204
|
+
style.setAttribute('type', 'text/css');
|
|
205
|
+
style.textContent = css;
|
|
206
|
+
parent.append(style);
|
|
207
|
+
return style;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Waits for image to fully load or throws an error if it fails.
|
|
212
|
+
*/
|
|
213
|
+
async function imageLoad(img) {
|
|
214
|
+
return new Promise((resolve, reject) => {
|
|
215
|
+
if (img.complete) {
|
|
216
|
+
resolve();
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
let onLoad;
|
|
220
|
+
let onError;
|
|
221
|
+
const removeListeners = () => {
|
|
222
|
+
img.removeEventListener('load', onLoad);
|
|
223
|
+
img.removeEventListener('error', onError);
|
|
224
|
+
};
|
|
225
|
+
onLoad = () => {
|
|
226
|
+
removeListeners();
|
|
227
|
+
resolve();
|
|
228
|
+
};
|
|
229
|
+
onError = () => {
|
|
230
|
+
removeListeners();
|
|
231
|
+
reject(new Error('Image failed to load'));
|
|
232
|
+
};
|
|
233
|
+
img.addEventListener('load', onLoad);
|
|
234
|
+
img.addEventListener('error', onError);
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Waits for the page to load.
|
|
240
|
+
* @param completely Whether or not to wait for resources to load as well.
|
|
241
|
+
*/
|
|
242
|
+
async function pageLoad(completely) {
|
|
243
|
+
return new Promise((resolve) => {
|
|
244
|
+
if (document.readyState === 'complete') {
|
|
245
|
+
resolve();
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
if (completely === true) {
|
|
249
|
+
window.addEventListener('load', () => resolve());
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
document.addEventListener('DOMContentLoaded', () => resolve());
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
87
256
|
function createFlagMessage(flag) {
|
|
88
257
|
const { message: messageHeader, values, type } = flag;
|
|
89
258
|
let message = messageHeader;
|
|
@@ -161,11 +330,18 @@ async function getOptions(flags) {
|
|
|
161
330
|
|
|
162
331
|
exports.$ = $;
|
|
163
332
|
exports.$$ = $$;
|
|
333
|
+
exports.addStyle = addStyle;
|
|
164
334
|
exports.alert = alert;
|
|
165
335
|
exports.asserted = asserted;
|
|
166
336
|
exports.confirm = confirm;
|
|
167
337
|
exports.ensureJoin = ensureJoin;
|
|
338
|
+
exports.fish = fish;
|
|
339
|
+
exports.fishResponse = fishResponse;
|
|
340
|
+
exports.fishX = fishX;
|
|
341
|
+
exports.fishXResponse = fishXResponse;
|
|
168
342
|
exports.getOptions = getOptions;
|
|
343
|
+
exports.getSearchParam = getSearchParam;
|
|
344
|
+
exports.imageLoad = imageLoad;
|
|
169
345
|
exports.isFalsy = isFalsy;
|
|
170
346
|
exports.isNotNullish = isNotNullish;
|
|
171
347
|
exports.isNullish = isNullish;
|
|
@@ -173,7 +349,9 @@ exports.isString = isString;
|
|
|
173
349
|
exports.isTruthy = isTruthy;
|
|
174
350
|
exports.logId = logId;
|
|
175
351
|
exports.noop = noop;
|
|
352
|
+
exports.pageLoad = pageLoad;
|
|
176
353
|
exports.prompt = prompt;
|
|
177
354
|
exports.scriptName = scriptName;
|
|
355
|
+
exports.setSearchParam = setSearchParam;
|
|
178
356
|
exports.sleep = sleep;
|
|
179
357
|
exports.tabURL = tabURL;
|
package/browser/index.d.ts
CHANGED
|
@@ -19,17 +19,67 @@ declare function alert(message?: string): void;
|
|
|
19
19
|
declare function confirm(message: string): boolean;
|
|
20
20
|
declare function prompt(message: string, _default?: string): string | null;
|
|
21
21
|
|
|
22
|
+
type Method = 'CONNECT' | 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT' | 'TRACE';
|
|
23
|
+
interface FishXOptions {
|
|
24
|
+
method?: Method;
|
|
25
|
+
anonymous?: boolean;
|
|
26
|
+
headers?: Record<string, string>;
|
|
27
|
+
body?: Blob | FormData | string;
|
|
28
|
+
timeOut?: number;
|
|
29
|
+
onProgress?: (response: VMScriptResponseObject<Blob>) => Promise<void> | void;
|
|
30
|
+
}
|
|
31
|
+
interface Fish<T> {
|
|
32
|
+
blob: (url: string, options?: T) => Promise<Blob>;
|
|
33
|
+
buffer: (url: string, options?: T) => Promise<ArrayBuffer>;
|
|
34
|
+
document: (url: string, options?: T) => Promise<Document>;
|
|
35
|
+
json: (url: string, options?: T) => Promise<object>;
|
|
36
|
+
text: (url: string, options?: T) => Promise<string>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
declare function fishResponse(url: string, options?: RequestInit): Promise<Response>;
|
|
40
|
+
|
|
41
|
+
declare function fishXResponse(url: string, fishOptions?: FishXOptions): Promise<Response>;
|
|
42
|
+
|
|
43
|
+
declare const fish: Fish<RequestInit>;
|
|
44
|
+
declare const fishX: Fish<FishXOptions>;
|
|
45
|
+
|
|
22
46
|
type Parent = Document | HTMLElement;
|
|
23
47
|
type Selectors = string[] | string;
|
|
24
48
|
declare function $<T = HTMLElement>(selectors: Selectors, parent?: Parent): T;
|
|
25
49
|
declare function $$<T extends Element = HTMLElement>(selectors: Selectors, parent?: Parent): NodeListOf<T>;
|
|
26
50
|
|
|
51
|
+
/**
|
|
52
|
+
* @param key The name of the param in the search query.
|
|
53
|
+
* @param fullURL If provided, it will be our target, otherwise it is the current location.
|
|
54
|
+
*/
|
|
55
|
+
declare function getSearchParam(key: string, fullURL?: string): string | undefined;
|
|
56
|
+
/**
|
|
57
|
+
*
|
|
58
|
+
* @param key The name of the param that is to be in the search query.
|
|
59
|
+
* @param value Its value.
|
|
60
|
+
* @param fullURL If provided, it will be our target, otherwise it is the current location.
|
|
61
|
+
*/
|
|
62
|
+
declare function setSearchParam(key: string, value: string, fullURL?: string): string;
|
|
63
|
+
|
|
27
64
|
declare const scriptName: string;
|
|
28
|
-
/** The identifier of the script to be used in logging */
|
|
65
|
+
/** The identifier of the script to be used in logging. */
|
|
29
66
|
declare const logId: string;
|
|
30
|
-
/** The initial tab URL on the script run */
|
|
67
|
+
/** The initial tab URL on the script run. */
|
|
31
68
|
declare const tabURL: string;
|
|
32
69
|
|
|
70
|
+
declare function addStyle(css: string, parent?: HTMLElement): HTMLStyleElement;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Waits for image to fully load or throws an error if it fails.
|
|
74
|
+
*/
|
|
75
|
+
declare function imageLoad(img: HTMLImageElement): Promise<void>;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Waits for the page to load.
|
|
79
|
+
* @param completely Whether or not to wait for resources to load as well.
|
|
80
|
+
*/
|
|
81
|
+
declare function pageLoad(completely: boolean): Promise<void>;
|
|
82
|
+
|
|
33
83
|
interface FlagBase {
|
|
34
84
|
name: string;
|
|
35
85
|
message: string;
|
|
@@ -56,4 +106,4 @@ type Options = Record<string, FlagValue>;
|
|
|
56
106
|
|
|
57
107
|
declare function getOptions(flags: Flag[]): Promise<Options>;
|
|
58
108
|
|
|
59
|
-
export { $, $$, Flag, Fn, Nullable, alert, asserted, confirm, ensureJoin, getOptions, isFalsy, isNotNullish, isNullish, isString, isTruthy, logId, noop, prompt, scriptName, sleep, tabURL };
|
|
109
|
+
export { $, $$, Flag, Fn, Nullable, addStyle, alert, asserted, confirm, ensureJoin, fish, fishResponse, fishX, fishXResponse, getOptions, getSearchParam, imageLoad, isFalsy, isNotNullish, isNullish, isString, isTruthy, logId, noop, pageLoad, prompt, scriptName, setSearchParam, sleep, tabURL };
|
package/browser/index.js
CHANGED
|
@@ -48,9 +48,9 @@ else {
|
|
|
48
48
|
infoObject = { script: { name: document.title } };
|
|
49
49
|
}
|
|
50
50
|
const scriptName = infoObject.script.name;
|
|
51
|
-
/** The identifier of the script to be used in logging */
|
|
51
|
+
/** The identifier of the script to be used in logging. */
|
|
52
52
|
const logId = `[${scriptName}]:`;
|
|
53
|
-
/** The initial tab URL on the script run */
|
|
53
|
+
/** The initial tab URL on the script run. */
|
|
54
54
|
const tabURL = window.location.href;
|
|
55
55
|
|
|
56
56
|
function alert(message) {
|
|
@@ -67,6 +67,90 @@ function prompt(message, _default) {
|
|
|
67
67
|
return window.prompt(`[ ${scriptName} ]\n\n${message}`, _default);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
async function fishResponse(url, options) {
|
|
71
|
+
const response = await fetch(url, options);
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
throw new Error(`Request to ${response.url} ended with ${response.status} status.`);
|
|
74
|
+
}
|
|
75
|
+
return response;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Note: to set the 'cookie' header, you have to set 'anonymous' to true.
|
|
79
|
+
async function fishXResponse(url, fishOptions) {
|
|
80
|
+
const { method, anonymous, headers, body, timeOut, onProgress } = fishOptions ?? {};
|
|
81
|
+
return new Promise((resolve, reject) => {
|
|
82
|
+
GM.xmlHttpRequest({
|
|
83
|
+
url,
|
|
84
|
+
method: method ?? 'GET',
|
|
85
|
+
headers,
|
|
86
|
+
anonymous,
|
|
87
|
+
data: body,
|
|
88
|
+
responseType: 'blob',
|
|
89
|
+
timeout: timeOut,
|
|
90
|
+
onprogress: onProgress,
|
|
91
|
+
onload({ response, statusText, status, finalUrl }) {
|
|
92
|
+
const ok = status >= 200 && status < 300;
|
|
93
|
+
if (!ok) {
|
|
94
|
+
reject(new Error(`Request to ${url} ended with ${status} status.`));
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const properResponse = new Response(response, {
|
|
98
|
+
statusText,
|
|
99
|
+
status,
|
|
100
|
+
});
|
|
101
|
+
Object.defineProperty(properResponse, 'url', { value: finalUrl });
|
|
102
|
+
resolve(properResponse);
|
|
103
|
+
},
|
|
104
|
+
onerror({ status }) {
|
|
105
|
+
reject(new Error(`Request to ${url} ended with ${status} status.`));
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async function fishBlob(url, options, x) {
|
|
112
|
+
const response = await (x ? fishXResponse : fishResponse)(url, options);
|
|
113
|
+
return response.blob();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async function fishBuffer(url, options, x) {
|
|
117
|
+
const response = await (x ? fishXResponse : fishResponse)(url, options);
|
|
118
|
+
return response.arrayBuffer();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async function fishDocument(url, options, x) {
|
|
122
|
+
const response = await (x ? fishXResponse : fishResponse)(url, options);
|
|
123
|
+
const responseText = await response.text();
|
|
124
|
+
const parser = new DOMParser();
|
|
125
|
+
return parser.parseFromString(responseText, 'text/html');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function fishJson(url, options, x) {
|
|
129
|
+
const response = await (x ? fishXResponse : fishResponse)(url, options);
|
|
130
|
+
return response.json();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async function fishText(url, options, x) {
|
|
134
|
+
const response = await (x ? fishXResponse : fishResponse)(url, options);
|
|
135
|
+
return response.text();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// https://httpbin.org/anything
|
|
139
|
+
const fish = {
|
|
140
|
+
blob: async (url, options) => fishBlob(url, options),
|
|
141
|
+
buffer: async (url, options) => fishBuffer(url, options),
|
|
142
|
+
document: async (url, options) => fishDocument(url, options),
|
|
143
|
+
json: async (url, options) => fishJson(url, options),
|
|
144
|
+
text: async (url, options) => fishText(url, options),
|
|
145
|
+
};
|
|
146
|
+
const fishX = {
|
|
147
|
+
blob: async (url, options) => fishBlob(url, options, true),
|
|
148
|
+
buffer: async (url, options) => fishBuffer(url, options, true),
|
|
149
|
+
document: async (url, options) => fishDocument(url, options, true),
|
|
150
|
+
json: async (url, options) => fishJson(url, options, true),
|
|
151
|
+
text: async (url, options) => fishText(url, options, true),
|
|
152
|
+
};
|
|
153
|
+
|
|
70
154
|
function $(selectors, parent) {
|
|
71
155
|
const element = (parent ?? document).querySelector(ensureJoin(selectors));
|
|
72
156
|
if (element === null) {
|
|
@@ -82,6 +166,91 @@ function $$(selectors, parent) {
|
|
|
82
166
|
return elements;
|
|
83
167
|
}
|
|
84
168
|
|
|
169
|
+
/**
|
|
170
|
+
* @param key The name of the param in the search query.
|
|
171
|
+
* @param fullURL If provided, it will be our target, otherwise it is the current location.
|
|
172
|
+
*/
|
|
173
|
+
function getSearchParam(key, fullURL) {
|
|
174
|
+
const { search } = new URL(fullURL ?? window.location.href);
|
|
175
|
+
const searchParams = new URLSearchParams(search);
|
|
176
|
+
const value = searchParams.get(key);
|
|
177
|
+
if (value === null) {
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
return value;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
*
|
|
184
|
+
* @param key The name of the param that is to be in the search query.
|
|
185
|
+
* @param value Its value.
|
|
186
|
+
* @param fullURL If provided, it will be our target, otherwise it is the current location.
|
|
187
|
+
*/
|
|
188
|
+
function setSearchParam(key, value, fullURL) {
|
|
189
|
+
const updatedURL = [];
|
|
190
|
+
const { origin, pathname, search, hash } = new URL(fullURL ?? window.location.href);
|
|
191
|
+
const searchParams = new URLSearchParams(search);
|
|
192
|
+
searchParams.set(key, value);
|
|
193
|
+
updatedURL.push(origin, pathname, '?', searchParams.toString());
|
|
194
|
+
if (hash !== '') {
|
|
195
|
+
updatedURL.push(hash);
|
|
196
|
+
}
|
|
197
|
+
return updatedURL.join('');
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function addStyle(css, parent = document.documentElement) {
|
|
201
|
+
const style = document.createElement('style');
|
|
202
|
+
style.setAttribute('type', 'text/css');
|
|
203
|
+
style.textContent = css;
|
|
204
|
+
parent.append(style);
|
|
205
|
+
return style;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Waits for image to fully load or throws an error if it fails.
|
|
210
|
+
*/
|
|
211
|
+
async function imageLoad(img) {
|
|
212
|
+
return new Promise((resolve, reject) => {
|
|
213
|
+
if (img.complete) {
|
|
214
|
+
resolve();
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
let onLoad;
|
|
218
|
+
let onError;
|
|
219
|
+
const removeListeners = () => {
|
|
220
|
+
img.removeEventListener('load', onLoad);
|
|
221
|
+
img.removeEventListener('error', onError);
|
|
222
|
+
};
|
|
223
|
+
onLoad = () => {
|
|
224
|
+
removeListeners();
|
|
225
|
+
resolve();
|
|
226
|
+
};
|
|
227
|
+
onError = () => {
|
|
228
|
+
removeListeners();
|
|
229
|
+
reject(new Error('Image failed to load'));
|
|
230
|
+
};
|
|
231
|
+
img.addEventListener('load', onLoad);
|
|
232
|
+
img.addEventListener('error', onError);
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Waits for the page to load.
|
|
238
|
+
* @param completely Whether or not to wait for resources to load as well.
|
|
239
|
+
*/
|
|
240
|
+
async function pageLoad(completely) {
|
|
241
|
+
return new Promise((resolve) => {
|
|
242
|
+
if (document.readyState === 'complete') {
|
|
243
|
+
resolve();
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (completely === true) {
|
|
247
|
+
window.addEventListener('load', () => resolve());
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
document.addEventListener('DOMContentLoaded', () => resolve());
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
85
254
|
function createFlagMessage(flag) {
|
|
86
255
|
const { message: messageHeader, values, type } = flag;
|
|
87
256
|
let message = messageHeader;
|
|
@@ -157,4 +326,4 @@ async function getOptions(flags) {
|
|
|
157
326
|
return options;
|
|
158
327
|
}
|
|
159
328
|
|
|
160
|
-
export { $, $$, alert, asserted, confirm, ensureJoin, getOptions, isFalsy, isNotNullish, isNullish, isString, isTruthy, logId, noop, prompt, scriptName, sleep, tabURL };
|
|
329
|
+
export { $, $$, addStyle, alert, asserted, confirm, ensureJoin, fish, fishResponse, fishX, fishXResponse, getOptions, getSearchParam, imageLoad, isFalsy, isNotNullish, isNullish, isString, isTruthy, logId, noop, pageLoad, prompt, scriptName, setSearchParam, sleep, tabURL };
|