@jeniex/utils 1.0.5 → 1.0.7
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 -1
- package/browser/index.d.ts +51 -1
- package/browser/index.js +172 -2
- package/package.json +1 -1
package/browser/index.cjs
CHANGED
|
@@ -41,8 +41,9 @@ async function sleep(milliSeconds) {
|
|
|
41
41
|
let infoObject;
|
|
42
42
|
if (typeof GM !== 'undefined') {
|
|
43
43
|
infoObject = GM.info;
|
|
44
|
+
// eslint-disable-next-line unicorn/no-negated-condition
|
|
44
45
|
}
|
|
45
|
-
else if (typeof GM_info
|
|
46
|
+
else if (typeof GM_info !== 'undefined') {
|
|
46
47
|
infoObject = GM_info;
|
|
47
48
|
}
|
|
48
49
|
else {
|
|
@@ -68,6 +69,90 @@ function prompt(message, _default) {
|
|
|
68
69
|
return window.prompt(`[ ${scriptName} ]\n\n${message}`, _default);
|
|
69
70
|
}
|
|
70
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
|
+
|
|
71
156
|
function $(selectors, parent) {
|
|
72
157
|
const element = (parent ?? document).querySelector(ensureJoin(selectors));
|
|
73
158
|
if (element === null) {
|
|
@@ -83,6 +168,91 @@ function $$(selectors, parent) {
|
|
|
83
168
|
return elements;
|
|
84
169
|
}
|
|
85
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 failed.
|
|
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
|
+
|
|
86
256
|
function createFlagMessage(flag) {
|
|
87
257
|
const { message: messageHeader, values, type } = flag;
|
|
88
258
|
let message = messageHeader;
|
|
@@ -160,11 +330,18 @@ async function getOptions(flags) {
|
|
|
160
330
|
|
|
161
331
|
exports.$ = $;
|
|
162
332
|
exports.$$ = $$;
|
|
333
|
+
exports.addStyle = addStyle;
|
|
163
334
|
exports.alert = alert;
|
|
164
335
|
exports.asserted = asserted;
|
|
165
336
|
exports.confirm = confirm;
|
|
166
337
|
exports.ensureJoin = ensureJoin;
|
|
338
|
+
exports.fish = fish;
|
|
339
|
+
exports.fishResponse = fishResponse;
|
|
340
|
+
exports.fishX = fishX;
|
|
341
|
+
exports.fishXResponse = fishXResponse;
|
|
167
342
|
exports.getOptions = getOptions;
|
|
343
|
+
exports.getSearchParam = getSearchParam;
|
|
344
|
+
exports.imageLoad = imageLoad;
|
|
168
345
|
exports.isFalsy = isFalsy;
|
|
169
346
|
exports.isNotNullish = isNotNullish;
|
|
170
347
|
exports.isNullish = isNullish;
|
|
@@ -172,7 +349,9 @@ exports.isString = isString;
|
|
|
172
349
|
exports.isTruthy = isTruthy;
|
|
173
350
|
exports.logId = logId;
|
|
174
351
|
exports.noop = noop;
|
|
352
|
+
exports.pageLoad = pageLoad;
|
|
175
353
|
exports.prompt = prompt;
|
|
176
354
|
exports.scriptName = scriptName;
|
|
355
|
+
exports.setSearchParam = setSearchParam;
|
|
177
356
|
exports.sleep = sleep;
|
|
178
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
65
|
/** The identifier of the script to be used in logging */
|
|
29
66
|
declare const logId: string;
|
|
30
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 failed.
|
|
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
|
@@ -39,8 +39,9 @@ async function sleep(milliSeconds) {
|
|
|
39
39
|
let infoObject;
|
|
40
40
|
if (typeof GM !== 'undefined') {
|
|
41
41
|
infoObject = GM.info;
|
|
42
|
+
// eslint-disable-next-line unicorn/no-negated-condition
|
|
42
43
|
}
|
|
43
|
-
else if (typeof GM_info
|
|
44
|
+
else if (typeof GM_info !== 'undefined') {
|
|
44
45
|
infoObject = GM_info;
|
|
45
46
|
}
|
|
46
47
|
else {
|
|
@@ -66,6 +67,90 @@ function prompt(message, _default) {
|
|
|
66
67
|
return window.prompt(`[ ${scriptName} ]\n\n${message}`, _default);
|
|
67
68
|
}
|
|
68
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
|
+
|
|
69
154
|
function $(selectors, parent) {
|
|
70
155
|
const element = (parent ?? document).querySelector(ensureJoin(selectors));
|
|
71
156
|
if (element === null) {
|
|
@@ -81,6 +166,91 @@ function $$(selectors, parent) {
|
|
|
81
166
|
return elements;
|
|
82
167
|
}
|
|
83
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 failed.
|
|
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
|
+
|
|
84
254
|
function createFlagMessage(flag) {
|
|
85
255
|
const { message: messageHeader, values, type } = flag;
|
|
86
256
|
let message = messageHeader;
|
|
@@ -156,4 +326,4 @@ async function getOptions(flags) {
|
|
|
156
326
|
return options;
|
|
157
327
|
}
|
|
158
328
|
|
|
159
|
-
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 };
|