@sv443-network/userutils 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,22 +1,10 @@
1
1
  # @sv443-network/userutils
2
2
 
3
- ## 0.1.4
3
+ ## 0.2.0
4
4
 
5
- ### Patch Changes
6
-
7
- - a1e8dec: please just work thanks
8
-
9
- ## 0.1.3
10
-
11
- ### Patch Changes
12
-
13
- - 9673cad: more testing
14
-
15
- ## 0.1.2
16
-
17
- ### Patch Changes
5
+ ### Minor Changes
18
6
 
19
- - 6eafb79: test publish workflow lol
7
+ - 0cf2254: add onSelector() to call a listener once a selector is found in the DOM
20
8
 
21
9
  ## 0.1.1
22
10
 
package/README.md CHANGED
@@ -8,6 +8,7 @@ Contains builtin TypeScript declarations.
8
8
  - [Installation](#installation)
9
9
  - [Features](#features)
10
10
  - [onSelector()](#onselector) - call a listener once a selector is found in the DOM
11
+ - [initOnSelector()](#initonselector) - needs to be called once to be able to use `onSelector()`
11
12
  - [autoPlural()](#autoplural) - automatically pluralize a string
12
13
  - [clamp()](#clamp) - clamp a number between a min and max value
13
14
  - [pauseFor()](#pausefor) - pause the execution of a function for a given amount of time
@@ -54,16 +55,89 @@ If you like using this library, please consider [supporting development](https:/
54
55
  ## Features:
55
56
 
56
57
  ### onSelector()
57
- \- UNFINISHED -
58
+ Usage:
59
+ ```ts
60
+ onSelector<TElement = HTMLElement>(selector: string, options: {
61
+ listener: (elements: TElement | NodeListOf<TElement>) => void,
62
+ all?: boolean,
63
+ continuous?: boolean,
64
+ }): void
65
+ ```
58
66
 
59
67
  Registers a listener to be called whenever the element(s) behind a selector is/are found in the DOM.
60
- In order to use this function, the MutationObservers have to be initialized with `initOnSelector()` first.
68
+ If the selector already exists, the listener will be called immediately.
69
+
70
+ If `all` is set to `true`, querySelectorAll() will be used instead and the listener will return a NodeList of matching elements.
71
+ This will also include elements that were already found in a previous listener call.
72
+ If set to `false` (default), querySelector() will be used and only the first element will be returned.
73
+
74
+ If `continuous` is set to `true`, the listener will not be deregistered after it was called once (defaults to false).
61
75
 
62
- Example:
76
+ When using TypeScript, the generic `TElement` can be used to specify the type of the element(s) that the listener will return.
77
+
78
+ ⚠️ In order to use this function, [`initOnSelector()`](#initonselector) has to be called as soon as possible.
79
+ This initialization function has to be called after `DOMContentLoaded` is fired (or immediately if `@run-at document-end` is set).
80
+
81
+ Calling onSelector() before `DOMContentLoaded` is fired will not throw an error, but it also won't trigger listeners until the DOM is accessible.
82
+
83
+ <details><summary><b>Example - click to view</b></summary>
84
+
63
85
  ```ts
64
- // TODO
86
+ document.addEventListener("DOMContentLoaded", initOnSelector);
87
+
88
+ // Continuously checks if `div` elements are added to the DOM, then returns all of them (even previously detected ones) in a NodeList
89
+ onSelector("div", {
90
+ listener: (element) => {
91
+ console.log("Elements found:", element);
92
+ },
93
+ all: true,
94
+ continuous: true,
95
+ });
96
+
97
+ // Checks if an input element with a value attribute of "5" is added to the DOM, then returns it and deregisters the listener
98
+ onSelector("input[value=\"5\"]", {
99
+ listener: (element) => {
100
+ console.log("Element found:", element);
101
+ },
102
+ });
65
103
  ```
66
104
 
105
+ </details>
106
+
107
+ <br>
108
+
109
+ ### initOnSelector()
110
+ Usage:
111
+ ```ts
112
+ initOnSelector(options: {
113
+ attributes?: boolean,
114
+ characterData?: boolean,
115
+ }): void
116
+ ```
117
+
118
+ Initializes the MutationObserver that is used by [`onSelector()`](#onselector) to check for the registered selectors whenever a DOM change occurs on the `<body>`
119
+ By default, this only checks if elements are added or removed (at any depth).
120
+
121
+ Set `attributes` to `true` to also check for attribute changes on every single descendant of the `<body>` (defaults to false).
122
+ Set `characterData` to `true` to also check for character data changes on every single descendant of the `<body>` (defaults to false).
123
+
124
+ ⚠️ Using these extra options can have a performance impact on larger sites or sites with a constantly changing DOM.
125
+
126
+ ⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
127
+
128
+ <details><summary><b>Example - click to view</b></summary>
129
+
130
+ ```ts
131
+ document.addEventListener("DOMContentLoaded", () => {
132
+ initOnSelector({
133
+ attributes: true,
134
+ characterData: true,
135
+ });
136
+ });
137
+ ```
138
+
139
+ </details>
140
+
67
141
  <br>
68
142
 
69
143
  ### autoPlural()
@@ -72,7 +146,8 @@ Usage: `autoPlural(str: string, num: number | Array | NodeList): string`
72
146
  Automatically pluralizes a string if the given number is not 1.
73
147
  If an array or NodeList is passed, the length of it will be used.
74
148
 
75
- Example:
149
+ <details><summary><b>Example - click to view</b></summary>
150
+
76
151
  ```ts
77
152
  autoPlural("apple", 0); // "apples"
78
153
  autoPlural("apple", 1); // "apple"
@@ -82,6 +157,8 @@ autoPlural("apple", [1]); // "apple"
82
157
  autoPlural("apple", [1, 2]); // "apples"
83
158
  ```
84
159
 
160
+ </details>
161
+
85
162
  <br>
86
163
 
87
164
  ### clamp()
@@ -89,13 +166,16 @@ Usage: `clamp(num: number, min: number, max: number): number`
89
166
 
90
167
  Clamps a number between a min and max value.
91
168
 
92
- Example:
169
+ <details><summary><b>Example - click to view</b></summary>
170
+
93
171
  ```ts
94
172
  clamp(5, 0, 10); // 5
95
173
  clamp(-1, 0, 10); // 0
96
174
  clamp(Infinity, 0, 10); // 10
97
175
  ```
98
176
 
177
+ </details>
178
+
99
179
  <br>
100
180
 
101
181
  ### pauseFor()
@@ -103,7 +183,8 @@ Usage: `pauseFor(ms: number): Promise<void>`
103
183
 
104
184
  Pauses async execution for a given amount of time.
105
185
 
106
- Example:
186
+ <details><summary><b>Example - click to view</b></summary>
187
+
107
188
  ```ts
108
189
  async function run() {
109
190
  console.log("Hello");
@@ -112,6 +193,8 @@ async function run() {
112
193
  }
113
194
  ```
114
195
 
196
+ </details>
197
+
115
198
  <br>
116
199
 
117
200
  ### debounce()
@@ -121,13 +204,16 @@ Debounces a function, meaning that it will only be called once after a given amo
121
204
  This is very useful for functions that are called repeatedly, like event listeners, to remove extraneous calls.
122
205
  The timeout will default to 300ms if left undefined.
123
206
 
124
- Example:
207
+ <details><summary><b>Example - click to view</b></summary>
208
+
125
209
  ```ts
126
210
  window.addEventListener("resize", debounce((event) => {
127
211
  console.log("Window was resized:", event);
128
212
  }, 500)); // 500ms timeout
129
213
  ```
130
214
 
215
+ </details>
216
+
131
217
  <br>
132
218
 
133
219
  ### getUnsafeWindow()
@@ -136,7 +222,8 @@ Usage: `getUnsafeWindow(): Window`
136
222
  Returns the unsafeWindow object or falls back to the regular window object if the `@grant unsafeWindow` is not given.
137
223
  Userscripts are sandboxed and do not have access to the regular window object, so this function is useful for websites that reject some events that were dispatched by the userscript.
138
224
 
139
- Example:
225
+ <details><summary><b>Example - click to view</b></summary>
226
+
140
227
  ```ts
141
228
  const mouseEvent = new MouseEvent("click", {
142
229
  view: getUnsafeWindow(),
@@ -144,15 +231,20 @@ const mouseEvent = new MouseEvent("click", {
144
231
  document.body.dispatchEvent(mouseEvent);
145
232
  ```
146
233
 
234
+ </details>
235
+
147
236
  <br>
148
237
 
149
238
  ### insertAfter()
150
239
  Usage: `insertAfter(beforeElement: HTMLElement, afterElement: HTMLElement): HTMLElement`
151
240
 
152
241
  Inserts the element passed as `afterElement` as a sibling after the passed `beforeElement`.
153
- The `afterElement` will be returned.
242
+ The passed `afterElement` will be returned.
243
+
244
+ ⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
154
245
 
155
- Example:
246
+ <details><summary><b>Example - click to view</b></summary>
247
+
156
248
  ```ts
157
249
  const beforeElement = document.querySelector("#before");
158
250
  const afterElement = document.createElement("div");
@@ -160,15 +252,20 @@ afterElement.innerText = "After";
160
252
  insertAfter(beforeElement, afterElement);
161
253
  ```
162
254
 
255
+ </details>
256
+
163
257
  <br>
164
258
 
165
259
  ### addParent()
166
260
  Usage: `addParent(element: HTMLElement, newParent: HTMLElement): HTMLElement`
167
261
 
168
262
  Adds a parent element around the passed `element` and returns the new parent.
169
- Previously registered event listeners should be kept intact.
263
+ Previously registered event listeners are kept intact.
170
264
 
171
- Example:
265
+ ⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
266
+
267
+ <details><summary><b>Example - click to view</b></summary>
268
+
172
269
  ```ts
173
270
  const element = document.querySelector("#element");
174
271
  const newParent = document.createElement("a");
@@ -176,15 +273,18 @@ newParent.href = "https://example.org/";
176
273
  addParent(element, newParent);
177
274
  ```
178
275
 
276
+ </details>
277
+
179
278
  <br>
180
279
 
181
280
  ### addGlobalStyle()
182
281
  Usage: `addGlobalStyle(css: string): void`
183
282
 
184
283
  Adds a global style to the page in form of a `<style>` element that's inserted into the `<head>`.
185
- This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
284
+ ⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
186
285
 
187
- Example:
286
+ <details><summary><b>Example - click to view</b></summary>
287
+
188
288
  ```ts
189
289
  document.addEventListener("DOMContentLoaded", () => {
190
290
  addGlobalStyle(`
@@ -195,43 +295,61 @@ document.addEventListener("DOMContentLoaded", () => {
195
295
  });
196
296
  ```
197
297
 
298
+ </details>
299
+
198
300
  <br>
199
301
 
200
302
  ### preloadImages()
201
- Usage: `preloadImages(...urls: string[]): Promise<void>`
303
+ Usage: `preloadImages(urls: string[], rejects?: boolean): Promise<void>`
202
304
 
203
305
  Preloads images into browser cache by creating an invisible `<img>` element for each URL passed.
204
306
  The images will be loaded in parallel and the returned Promise will only resolve once all images have been loaded.
205
- The resulting PromiseSettledResult array will contain the image elements if resolved, or an ErrorEvent if rejected.
307
+ The resulting PromiseSettledResult array will contain the image elements if resolved, or an ErrorEvent if rejected, but only if `rejects` is set to true.
206
308
 
207
- Example:
309
+ <details><summary><b>Example - click to view</b></summary>
310
+
208
311
  ```ts
209
- preloadImages(
312
+ preloadImages([
210
313
  "https://example.org/image1.png",
211
314
  "https://example.org/image2.png",
212
315
  "https://example.org/image3.png",
213
- ).then((results) => {
214
- console.log("Images preloaded. Results:", results);
215
- });
316
+ ], true)
317
+ .then((results) => {
318
+ console.log("Images preloaded. Results:", results);
319
+ });
216
320
  ```
217
321
 
322
+ </details>
323
+
218
324
  <br>
219
325
 
220
326
  ### fetchAdvanced()
221
- Usage: `fetchAdvanced(url: string, options?: FetchAdvancedOptions): Promise<Response>`
327
+ Usage:
328
+ ```ts
329
+ fetchAdvanced(url: string, options?: {
330
+ timeout?: number,
331
+ // any other options from fetch() except for signal
332
+ }): Promise<Response>
333
+ ```
222
334
 
223
335
  A wrapper around the native `fetch()` function that adds options like a timeout property.
224
336
  The timeout will default to 10 seconds if left undefined.
225
337
 
226
- Example:
338
+ <details><summary><b>Example - click to view</b></summary>
339
+
227
340
  ```ts
228
- fetchAdvanced("https://example.org/", {
341
+ fetchAdvanced("https://api.example.org/data", {
229
342
  timeout: 5000,
230
- }).then((response) => {
231
- console.log("Response:", response);
343
+ headers: {
344
+ "Accept": "application/json",
345
+ },
346
+ }).then(async (response) => {
347
+ console.log("Data:", await response.json());
232
348
  });
233
349
  ```
234
350
 
351
+ </details>
352
+
235
353
  <br>
236
354
 
237
355
  ### openInNewTab()
@@ -241,29 +359,38 @@ Creates an invisible anchor with a `_blank` target and clicks it.
241
359
  Contrary to `window.open()`, this has a lesser chance to get blocked by the browser's popup blocker and doesn't open the URL as a new window.
242
360
  This function has to be run in relatively quick succession in response to a user interaction event, else the browser might reject it.
243
361
 
244
- Example:
362
+ ⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
363
+
364
+ <details><summary><b>Example - click to view</b></summary>
365
+
245
366
  ```ts
246
367
  document.querySelector("#button").addEventListener("click", () => {
247
368
  openInNewTab("https://example.org/");
248
369
  });
249
370
  ```
250
371
 
372
+ </details>
373
+
251
374
  <br>
252
375
 
253
376
  ### interceptEvent()
254
377
  Usage: `interceptEvent(eventObject: EventTarget, eventName: string, predicate: () => boolean): void`
255
378
 
256
379
  Intercepts all events dispatched on the `eventObject` and prevents the listeners from being called as long as the predicate function returns a truthy value.
257
- This function should be called as soon as possible (I recommend using `@run-at document-start`), as it will only intercept events that are added after this function is called.
258
380
  Calling this function will set the `Error.stackTraceLimit` to 1000 to ensure the stack trace is preserved.
259
381
 
260
- Example:
382
+ ⚠️ This function should be called as soon as possible (I recommend using `@run-at document-start`), as it will only intercept events that are *attached* after this function is called.
383
+
384
+ <details><summary><b>Example - click to view</b></summary>
385
+
261
386
  ```ts
262
387
  interceptEvent(document.body, "click", () => {
263
388
  return true; // prevent all click events on the body
264
389
  });
265
390
  ```
266
391
 
392
+ </details>
393
+
267
394
  <br>
268
395
 
269
396
  ### interceptWindowEvent()
@@ -272,13 +399,18 @@ Usage: `interceptWindowEvent(eventName: string, predicate: () => boolean): void`
272
399
  Intercepts all events dispatched on the `window` object and prevents the listeners from being called as long as the predicate function returns a truthy value.
273
400
  This is essentially the same as [`interceptEvent()`](#interceptevent), but automatically uses the `unsafeWindow` (or falls back to regular `window`).
274
401
 
275
- Example:
402
+ ⚠️ This function should be called as soon as possible (I recommend using `@run-at document-start`), as it will only intercept events that are *attached* after this function is called.
403
+
404
+ <details><summary><b>Example - click to view</b></summary>
405
+
276
406
  ```ts
277
407
  interceptWindowEvent("beforeunload", () => {
278
408
  return true; // prevent the pesky "Are you sure you want to leave this page?" popup
279
409
  });
280
410
  ```
281
411
 
412
+ </details>
413
+
282
414
 
283
415
  <br><br>
284
416
 
package/dist/index.d.mts CHANGED
@@ -1,12 +1,28 @@
1
- type SelectorExistsOpts = {
2
- /** The selector to check for */
3
- selector: string;
4
- /** Whether to use `querySelectorAll()` instead */
5
- all?: boolean;
6
- /** Whether to call the listener continuously instead of once */
1
+ type InitOnSelectorOpts = {
2
+ /** Set to true if mutations to any element's attributes are to also trigger the onSelector check (warning: this might draw a lot of performance on larger sites) */
3
+ attributes?: boolean;
4
+ /** Set to true if mutations to any element's character data are to also trigger the onSelector check (warning: this might draw a lot of performance on larger sites) */
5
+ characterData?: boolean;
6
+ };
7
+ type OnSelectorOpts<TElem extends Element = HTMLElement> = SelectorOptsOne<TElem> | SelectorOptsAll<TElem>;
8
+ type SelectorOptsOne<TElem extends Element> = SelectorOptsBase & {
9
+ /** Whether to use `querySelectorAll()` instead - default is false */
10
+ all?: false;
11
+ /** Gets called whenever the selector was found in the DOM */
12
+ listener: (element: TElem) => void;
13
+ };
14
+ type SelectorOptsAll<TElem extends Element> = SelectorOptsBase & {
15
+ /** Whether to use `querySelectorAll()` instead - default is false */
16
+ all: true;
17
+ /** Gets called whenever the selector was found in the DOM */
18
+ listener: (elements: NodeListOf<TElem>) => void;
19
+ };
20
+ type SelectorOptsBase = {
21
+ /** Whether to call the listener continuously instead of once - default is false */
7
22
  continuous?: boolean;
8
23
  };
9
24
  type FetchAdvancedOpts = RequestInit & Partial<{
25
+ /** Timeout in milliseconds after which the fetch call will be canceled with an AbortController signal */
10
26
  timeout: number;
11
27
  }>;
12
28
 
@@ -77,10 +93,17 @@ declare function interceptWindowEvent(eventName: keyof WindowEventMap, predicate
77
93
  * Calls the `listener` as soon as the `selector` exists in the DOM.
78
94
  * Listeners are deleted when they are called once, unless `options.continuous` is set.
79
95
  * Multiple listeners with the same selector may be registered.
80
- * @template TElem The type of element that this selector will return - FIXME: listener inferring doesn't work when this generic is given
96
+ * @param selector The selector to listen for
97
+ * @param options Used for switching to `querySelectorAll()` and for calling the listener continuously
98
+ * @template TElem The type of element that the listener will return as its argument (defaults to the generic HTMLElement)
99
+ */
100
+ declare function onSelector<TElem extends Element = HTMLElement>(selector: string, options: OnSelectorOpts<TElem>): void;
101
+ /** Removes all listeners registered in `onSelector()` that have the given selector */
102
+ declare function removeOnSelector(selector: string): boolean;
103
+ /**
104
+ * Initializes a MutationObserver that checks for all registered selectors whenever an element is added to or removed from the `<body>`
105
+ * @param opts For fine-tuning when the MutationObserver checks for the selectors
81
106
  */
82
- declare function onSelector<TElem = HTMLElement, TOpts extends SelectorExistsOpts = SelectorExistsOpts>(options: TOpts, listener: (element: TOpts["all"] extends true ? (TElem extends HTMLElement ? NodeListOf<TElem> : TElem) : TElem) => void): void;
83
- /** Removes all listeners registered in `onSelector()` with a matching selector property */
84
- declare function removeOnSelector(selector: string): void;
107
+ declare function initOnSelector(opts?: InitOnSelectorOpts): void;
85
108
 
86
- export { FetchAdvancedOpts, SelectorExistsOpts, addGlobalStyle, addParent, autoPlural, clamp, debounce, fetchAdvanced, getUnsafeWindow, insertAfter, interceptEvent, interceptWindowEvent, onSelector, openInNewTab, pauseFor, preloadImages, removeOnSelector };
109
+ export { FetchAdvancedOpts, InitOnSelectorOpts, OnSelectorOpts, addGlobalStyle, addParent, autoPlural, clamp, debounce, fetchAdvanced, getUnsafeWindow, initOnSelector, insertAfter, interceptEvent, interceptWindowEvent, onSelector, openInNewTab, pauseFor, preloadImages, removeOnSelector };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,28 @@
1
- type SelectorExistsOpts = {
2
- /** The selector to check for */
3
- selector: string;
4
- /** Whether to use `querySelectorAll()` instead */
5
- all?: boolean;
6
- /** Whether to call the listener continuously instead of once */
1
+ type InitOnSelectorOpts = {
2
+ /** Set to true if mutations to any element's attributes are to also trigger the onSelector check (warning: this might draw a lot of performance on larger sites) */
3
+ attributes?: boolean;
4
+ /** Set to true if mutations to any element's character data are to also trigger the onSelector check (warning: this might draw a lot of performance on larger sites) */
5
+ characterData?: boolean;
6
+ };
7
+ type OnSelectorOpts<TElem extends Element = HTMLElement> = SelectorOptsOne<TElem> | SelectorOptsAll<TElem>;
8
+ type SelectorOptsOne<TElem extends Element> = SelectorOptsBase & {
9
+ /** Whether to use `querySelectorAll()` instead - default is false */
10
+ all?: false;
11
+ /** Gets called whenever the selector was found in the DOM */
12
+ listener: (element: TElem) => void;
13
+ };
14
+ type SelectorOptsAll<TElem extends Element> = SelectorOptsBase & {
15
+ /** Whether to use `querySelectorAll()` instead - default is false */
16
+ all: true;
17
+ /** Gets called whenever the selector was found in the DOM */
18
+ listener: (elements: NodeListOf<TElem>) => void;
19
+ };
20
+ type SelectorOptsBase = {
21
+ /** Whether to call the listener continuously instead of once - default is false */
7
22
  continuous?: boolean;
8
23
  };
9
24
  type FetchAdvancedOpts = RequestInit & Partial<{
25
+ /** Timeout in milliseconds after which the fetch call will be canceled with an AbortController signal */
10
26
  timeout: number;
11
27
  }>;
12
28
 
@@ -77,10 +93,17 @@ declare function interceptWindowEvent(eventName: keyof WindowEventMap, predicate
77
93
  * Calls the `listener` as soon as the `selector` exists in the DOM.
78
94
  * Listeners are deleted when they are called once, unless `options.continuous` is set.
79
95
  * Multiple listeners with the same selector may be registered.
80
- * @template TElem The type of element that this selector will return - FIXME: listener inferring doesn't work when this generic is given
96
+ * @param selector The selector to listen for
97
+ * @param options Used for switching to `querySelectorAll()` and for calling the listener continuously
98
+ * @template TElem The type of element that the listener will return as its argument (defaults to the generic HTMLElement)
99
+ */
100
+ declare function onSelector<TElem extends Element = HTMLElement>(selector: string, options: OnSelectorOpts<TElem>): void;
101
+ /** Removes all listeners registered in `onSelector()` that have the given selector */
102
+ declare function removeOnSelector(selector: string): boolean;
103
+ /**
104
+ * Initializes a MutationObserver that checks for all registered selectors whenever an element is added to or removed from the `<body>`
105
+ * @param opts For fine-tuning when the MutationObserver checks for the selectors
81
106
  */
82
- declare function onSelector<TElem = HTMLElement, TOpts extends SelectorExistsOpts = SelectorExistsOpts>(options: TOpts, listener: (element: TOpts["all"] extends true ? (TElem extends HTMLElement ? NodeListOf<TElem> : TElem) : TElem) => void): void;
83
- /** Removes all listeners registered in `onSelector()` with a matching selector property */
84
- declare function removeOnSelector(selector: string): void;
107
+ declare function initOnSelector(opts?: InitOnSelectorOpts): void;
85
108
 
86
- export { FetchAdvancedOpts, SelectorExistsOpts, addGlobalStyle, addParent, autoPlural, clamp, debounce, fetchAdvanced, getUnsafeWindow, insertAfter, interceptEvent, interceptWindowEvent, onSelector, openInNewTab, pauseFor, preloadImages, removeOnSelector };
109
+ export { FetchAdvancedOpts, InitOnSelectorOpts, OnSelectorOpts, addGlobalStyle, addParent, autoPlural, clamp, debounce, fetchAdvanced, getUnsafeWindow, initOnSelector, insertAfter, interceptEvent, interceptWindowEvent, onSelector, openInNewTab, pauseFor, preloadImages, removeOnSelector };
package/dist/index.js CHANGED
@@ -1,19 +1,20 @@
1
1
  'use strict';
2
2
 
3
- var E=Object.defineProperty,T=Object.defineProperties;var x=Object.getOwnPropertyDescriptors;var l=Object.getOwnPropertySymbols;var v=Object.prototype.hasOwnProperty,b=Object.prototype.propertyIsEnumerable;var p=(t,e,n)=>e in t?E(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,u=(t,e)=>{for(var n in e||(e={}))v.call(e,n)&&p(t,n,e[n]);if(l)for(var n of l(e))b.call(e,n)&&p(t,n,e[n]);return t},m=(t,e)=>T(t,x(e));var f=(t,e,n)=>new Promise((o,r)=>{var a=s=>{try{c(n.next(s));}catch(d){r(d);}},i=s=>{try{c(n.throw(s));}catch(d){r(d);}},c=s=>s.done?o(s.value):Promise.resolve(s.value).then(a,i);c((n=n.apply(t,e)).next());});function h(t,e){return (Array.isArray(e)||e instanceof NodeList)&&(e=e.length),`${t}${e===1?"":"s"}`}function O(t,e,n){return Math.max(Math.min(t,n),e)}function w(t){return new Promise(e=>{setTimeout(e,t);})}function A(t,e=300){let n;return function(...o){clearTimeout(n),n=setTimeout(()=>t.apply(this,o),e);}}function y(){try{return unsafeWindow}catch(t){return window}}function M(t,e){var n;return (n=t.parentNode)==null||n.insertBefore(e,t.nextSibling),e}function _(t,e){let n=t.parentNode;if(!n)throw new Error("Element doesn't have a parent node");return n.replaceChild(e,t),e.appendChild(t),e}function k(t){let e=document.createElement("style");e.innerHTML=t,document.head.appendChild(e);}function S(t,e=!1){let n=t.map(o=>new Promise((r,a)=>{let i=new Image;i.src=o,i.addEventListener("load",()=>r(i)),i.addEventListener("error",c=>e&&a(c));}));return Promise.allSettled(n)}function H(n){return f(this,arguments,function*(t,e={}){let{timeout:o=1e4}=e,r=new AbortController,a=setTimeout(()=>r.abort(),o),i=yield fetch(t,m(u({},e),{signal:r.signal}));return clearTimeout(a),i})}function N(t){let e=document.createElement("a");Object.assign(e,{className:"userutils-open-in-new-tab",target:"_blank",rel:"noopener noreferrer",href:t}),e.style.display="none",document.body.appendChild(e),e.click(),setTimeout(e.remove,50);}function g(t,e,n){typeof Error.stackTraceLimit=="number"&&Error.stackTraceLimit<1e3&&(Error.stackTraceLimit=1e3),function(o){element.__proto__.addEventListener=function(...r){if(!(r[0]===e&&n()))return o.apply(this,r)};}(t.__proto__.addEventListener);}function j(t,e){return g(y(),t,e)}function F(t,e){}function W(t){}
3
+ var b=Object.defineProperty,v=Object.defineProperties;var y=Object.getOwnPropertyDescriptors;var m=Object.getOwnPropertySymbols;var x=Object.prototype.hasOwnProperty,g=Object.prototype.propertyIsEnumerable;var f=(t,e,n)=>e in t?b(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,u=(t,e)=>{for(var n in e||(e={}))x.call(e,n)&&f(t,n,e[n]);if(m)for(var n of m(e))g.call(e,n)&&f(t,n,e[n]);return t},d=(t,e)=>v(t,y(e));var E=(t,e,n)=>new Promise((r,o)=>{var s=c=>{try{l(n.next(c));}catch(p){o(p);}},i=c=>{try{l(n.throw(c));}catch(p){o(p);}},l=c=>c.done?r(c.value):Promise.resolve(c.value).then(s,i);l((n=n.apply(t,e)).next());});function w(t,e){return (Array.isArray(e)||e instanceof NodeList)&&(e=e.length),`${t}${e===1?"":"s"}`}function M(t,e,n){return Math.max(Math.min(t,n),e)}function S(t){return new Promise(e=>{setTimeout(e,t);})}function A(t,e=300){let n;return function(...r){clearTimeout(n),n=setTimeout(()=>t.apply(this,r),e);}}function h(){try{return unsafeWindow}catch(t){return window}}function _(t,e){var n;return (n=t.parentNode)==null||n.insertBefore(e,t.nextSibling),e}function k(t,e){let n=t.parentNode;if(!n)throw new Error("Element doesn't have a parent node");return n.replaceChild(e,t),e.appendChild(t),e}function H(t){let e=document.createElement("style");e.innerHTML=t,document.head.appendChild(e);}function I(t,e=!1){let n=t.map(r=>new Promise((o,s)=>{let i=new Image;i.src=r,i.addEventListener("load",()=>o(i)),i.addEventListener("error",l=>e&&s(l));}));return Promise.allSettled(n)}function j(n){return E(this,arguments,function*(t,e={}){let{timeout:r=1e4}=e,o=new AbortController,s=setTimeout(()=>o.abort(),r),i=yield fetch(t,d(u({},e),{signal:o.signal}));return clearTimeout(s),i})}function N(t){let e=document.createElement("a");Object.assign(e,{className:"userutils-open-in-new-tab",target:"_blank",rel:"noopener noreferrer",href:t}),e.style.display="none",document.body.appendChild(e),e.click(),setTimeout(e.remove,50);}function O(t,e,n){typeof Error.stackTraceLimit=="number"&&Error.stackTraceLimit<1e3&&(Error.stackTraceLimit=1e3),function(r){element.__proto__.addEventListener=function(...o){if(!(o[0]===e&&n()))return r.apply(this,o)};}(t.__proto__.addEventListener);}function P(t,e){return O(h(),t,e)}var a=new Map;function W(t,e){let n=[];a.has(t)&&(n=a.get(t)),n.push(e),a.set(t,n),T(t,n);}function q(t){return a.delete(t)}function T(t,e){let n=[];e.forEach((r,o)=>{try{let s=r.all?document.querySelectorAll(t):document.querySelector(t);s&&(r.listener(s),r.continuous||n.push(o));}catch(s){}}),n.length>0&&a.set(t,e.filter((r,o)=>!n.includes(o)));}function $(t={}){new MutationObserver(()=>{for(let[n,r]of a.entries())T(n,r);}).observe(document.body,d(u({},t),{childList:!0}));}
4
4
 
5
- exports.addGlobalStyle = k;
6
- exports.addParent = _;
7
- exports.autoPlural = h;
8
- exports.clamp = O;
5
+ exports.addGlobalStyle = H;
6
+ exports.addParent = k;
7
+ exports.autoPlural = w;
8
+ exports.clamp = M;
9
9
  exports.debounce = A;
10
- exports.fetchAdvanced = H;
11
- exports.getUnsafeWindow = y;
12
- exports.insertAfter = M;
13
- exports.interceptEvent = g;
14
- exports.interceptWindowEvent = j;
15
- exports.onSelector = F;
10
+ exports.fetchAdvanced = j;
11
+ exports.getUnsafeWindow = h;
12
+ exports.initOnSelector = $;
13
+ exports.insertAfter = _;
14
+ exports.interceptEvent = O;
15
+ exports.interceptWindowEvent = P;
16
+ exports.onSelector = W;
16
17
  exports.openInNewTab = N;
17
- exports.pauseFor = w;
18
- exports.preloadImages = S;
19
- exports.removeOnSelector = W;
18
+ exports.pauseFor = S;
19
+ exports.preloadImages = I;
20
+ exports.removeOnSelector = q;
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- var E=Object.defineProperty,T=Object.defineProperties;var x=Object.getOwnPropertyDescriptors;var l=Object.getOwnPropertySymbols;var v=Object.prototype.hasOwnProperty,b=Object.prototype.propertyIsEnumerable;var p=(t,e,n)=>e in t?E(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,u=(t,e)=>{for(var n in e||(e={}))v.call(e,n)&&p(t,n,e[n]);if(l)for(var n of l(e))b.call(e,n)&&p(t,n,e[n]);return t},m=(t,e)=>T(t,x(e));var f=(t,e,n)=>new Promise((o,r)=>{var a=s=>{try{c(n.next(s));}catch(d){r(d);}},i=s=>{try{c(n.throw(s));}catch(d){r(d);}},c=s=>s.done?o(s.value):Promise.resolve(s.value).then(a,i);c((n=n.apply(t,e)).next());});function h(t,e){return (Array.isArray(e)||e instanceof NodeList)&&(e=e.length),`${t}${e===1?"":"s"}`}function O(t,e,n){return Math.max(Math.min(t,n),e)}function w(t){return new Promise(e=>{setTimeout(e,t);})}function A(t,e=300){let n;return function(...o){clearTimeout(n),n=setTimeout(()=>t.apply(this,o),e);}}function y(){try{return unsafeWindow}catch(t){return window}}function M(t,e){var n;return (n=t.parentNode)==null||n.insertBefore(e,t.nextSibling),e}function _(t,e){let n=t.parentNode;if(!n)throw new Error("Element doesn't have a parent node");return n.replaceChild(e,t),e.appendChild(t),e}function k(t){let e=document.createElement("style");e.innerHTML=t,document.head.appendChild(e);}function S(t,e=!1){let n=t.map(o=>new Promise((r,a)=>{let i=new Image;i.src=o,i.addEventListener("load",()=>r(i)),i.addEventListener("error",c=>e&&a(c));}));return Promise.allSettled(n)}function H(n){return f(this,arguments,function*(t,e={}){let{timeout:o=1e4}=e,r=new AbortController,a=setTimeout(()=>r.abort(),o),i=yield fetch(t,m(u({},e),{signal:r.signal}));return clearTimeout(a),i})}function N(t){let e=document.createElement("a");Object.assign(e,{className:"userutils-open-in-new-tab",target:"_blank",rel:"noopener noreferrer",href:t}),e.style.display="none",document.body.appendChild(e),e.click(),setTimeout(e.remove,50);}function g(t,e,n){typeof Error.stackTraceLimit=="number"&&Error.stackTraceLimit<1e3&&(Error.stackTraceLimit=1e3),function(o){element.__proto__.addEventListener=function(...r){if(!(r[0]===e&&n()))return o.apply(this,r)};}(t.__proto__.addEventListener);}function j(t,e){return g(y(),t,e)}function F(t,e){}function W(t){}
1
+ var b=Object.defineProperty,v=Object.defineProperties;var y=Object.getOwnPropertyDescriptors;var m=Object.getOwnPropertySymbols;var x=Object.prototype.hasOwnProperty,g=Object.prototype.propertyIsEnumerable;var f=(t,e,n)=>e in t?b(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,u=(t,e)=>{for(var n in e||(e={}))x.call(e,n)&&f(t,n,e[n]);if(m)for(var n of m(e))g.call(e,n)&&f(t,n,e[n]);return t},d=(t,e)=>v(t,y(e));var E=(t,e,n)=>new Promise((r,o)=>{var s=c=>{try{l(n.next(c));}catch(p){o(p);}},i=c=>{try{l(n.throw(c));}catch(p){o(p);}},l=c=>c.done?r(c.value):Promise.resolve(c.value).then(s,i);l((n=n.apply(t,e)).next());});function w(t,e){return (Array.isArray(e)||e instanceof NodeList)&&(e=e.length),`${t}${e===1?"":"s"}`}function M(t,e,n){return Math.max(Math.min(t,n),e)}function S(t){return new Promise(e=>{setTimeout(e,t);})}function A(t,e=300){let n;return function(...r){clearTimeout(n),n=setTimeout(()=>t.apply(this,r),e);}}function h(){try{return unsafeWindow}catch(t){return window}}function _(t,e){var n;return (n=t.parentNode)==null||n.insertBefore(e,t.nextSibling),e}function k(t,e){let n=t.parentNode;if(!n)throw new Error("Element doesn't have a parent node");return n.replaceChild(e,t),e.appendChild(t),e}function H(t){let e=document.createElement("style");e.innerHTML=t,document.head.appendChild(e);}function I(t,e=!1){let n=t.map(r=>new Promise((o,s)=>{let i=new Image;i.src=r,i.addEventListener("load",()=>o(i)),i.addEventListener("error",l=>e&&s(l));}));return Promise.allSettled(n)}function j(n){return E(this,arguments,function*(t,e={}){let{timeout:r=1e4}=e,o=new AbortController,s=setTimeout(()=>o.abort(),r),i=yield fetch(t,d(u({},e),{signal:o.signal}));return clearTimeout(s),i})}function N(t){let e=document.createElement("a");Object.assign(e,{className:"userutils-open-in-new-tab",target:"_blank",rel:"noopener noreferrer",href:t}),e.style.display="none",document.body.appendChild(e),e.click(),setTimeout(e.remove,50);}function O(t,e,n){typeof Error.stackTraceLimit=="number"&&Error.stackTraceLimit<1e3&&(Error.stackTraceLimit=1e3),function(r){element.__proto__.addEventListener=function(...o){if(!(o[0]===e&&n()))return r.apply(this,o)};}(t.__proto__.addEventListener);}function P(t,e){return O(h(),t,e)}var a=new Map;function W(t,e){let n=[];a.has(t)&&(n=a.get(t)),n.push(e),a.set(t,n),T(t,n);}function q(t){return a.delete(t)}function T(t,e){let n=[];e.forEach((r,o)=>{try{let s=r.all?document.querySelectorAll(t):document.querySelector(t);s&&(r.listener(s),r.continuous||n.push(o));}catch(s){}}),n.length>0&&a.set(t,e.filter((r,o)=>!n.includes(o)));}function $(t={}){new MutationObserver(()=>{for(let[n,r]of a.entries())T(n,r);}).observe(document.body,d(u({},t),{childList:!0}));}
2
2
 
3
- export { k as addGlobalStyle, _ as addParent, h as autoPlural, O as clamp, A as debounce, H as fetchAdvanced, y as getUnsafeWindow, M as insertAfter, g as interceptEvent, j as interceptWindowEvent, F as onSelector, N as openInNewTab, w as pauseFor, S as preloadImages, W as removeOnSelector };
3
+ export { H as addGlobalStyle, k as addParent, w as autoPlural, M as clamp, A as debounce, j as fetchAdvanced, h as getUnsafeWindow, $ as initOnSelector, _ as insertAfter, O as interceptEvent, P as interceptWindowEvent, W as onSelector, N as openInNewTab, S as pauseFor, I as preloadImages, q as removeOnSelector };
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@sv443-network/userutils",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "description": "Library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, modify the DOM more easily and more ",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
8
8
  "scripts": {
9
9
  "lint": "tsc && eslint .",
10
- "prepare-build": "tsup lib/index.ts --format cjs,esm --dts --clean --treeshake",
11
- "build": "npm run prepare-build -- --minify",
12
- "build-dev": "npm run prepare-build -- --sourcemap --watch",
10
+ "build-common": "tsup lib/index.ts --format cjs,esm --dts --clean --treeshake",
11
+ "build": "npm run build-common -- --minify",
12
+ "dev": "npm run build-common -- --sourcemap --watch",
13
13
  "publish-package": "npm run build && changeset publish"
14
14
  },
15
15
  "repository": {