billy-herrington-utils 1.1.8 → 1.1.9
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/LICENSE +21 -21
- package/README.md +61 -61
- package/dist/billy-herrington-utils.es.js +11 -1
- package/dist/billy-herrington-utils.es.js.map +1 -1
- package/dist/billy-herrington-utils.umd.js +11 -1
- package/dist/billy-herrington-utils.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +19 -19
- package/src/utils/arrays/index.ts +7 -7
- package/src/utils/async/index.ts +75 -75
- package/src/utils/device/index.ts +2 -2
- package/src/utils/dom/index.ts +89 -89
- package/src/utils/events/index.ts +30 -30
- package/src/utils/fetch/index.ts +22 -22
- package/src/utils/math/index.ts +3 -3
- package/src/utils/observers/index.ts +58 -58
- package/src/utils/parsers/index.ts +40 -28
- package/src/utils/strings/index.ts +7 -7
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024 smartacephale
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 smartacephale
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
### _daddy told us not to be ashamed of our utils_
|
|
2
|
-

|
|
3
|
-
|
|
4
|
-
```
|
|
5
|
-
<script src="https://unpkg.com/billy-herrington-utils"></script>
|
|
6
|
-
```
|
|
7
|
-
```
|
|
8
|
-
<script src="https://unpkg.com/billy-herrington-utils/dist/billy-herrington-utils.umd.js"></script>
|
|
9
|
-
<script>
|
|
10
|
-
const { Tick } = window.bhutils;
|
|
11
|
-
</script>
|
|
12
|
-
```
|
|
13
|
-
```
|
|
14
|
-
npm i billy-herrington-utils
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
**A comprehensive collection of utility 🛠️ functions to make dungeon life easier.**
|
|
18
|
-
|
|
19
|
-
**Key features:**
|
|
20
|
-
|
|
21
|
-
* **String manipulation:** Easily parse, sanitize, and convert strings.
|
|
22
|
-
* **Time and date:** Work with time and date values effortlessly.
|
|
23
|
-
* **DOM manipulation:** Interact with DOM elements like a pro.
|
|
24
|
-
* **Networking:** Make HTTP requests and handle data with ease.
|
|
25
|
-
* **Miscellaneous:** A variety of other useful functions for common tasks.
|
|
26
|
-
|
|
27
|
-
## **Documentation**
|
|
28
|
-
|
|
29
|
-
| Function | Short Explanation | Input Parameters | Example Input/Output or Usage |
|
|
30
|
-
|---|---|---|---|
|
|
31
|
-
| `stringToWords(s)` | Splits a string into an array of words. | `s: string` | `stringToWords("Hello, world!")` -> `["hello", "world"]` |
|
|
32
|
-
| `sanitizeStr(s)` | Sanitizes a string by removing newlines, tabs, and extra spaces. | `s: string` | `sanitizeStr("Hello\nWorld\t")` -> `hello world` |
|
|
33
|
-
| `timeToSeconds(timeStr)` | Converts a time string to seconds. | `timeStr: string` | `timeToSeconds("1h30m")` -> `5400` |
|
|
34
|
-
| `parseIntegerOr(value, defaultValue)` | Parses a string as an integer. | `value: string`, `defaultValue: number` | `parseIntegerOr("10", 0)` -> `10`, `parseIntegerOr("abc", 0)` -> `0` |
|
|
35
|
-
| `parseDataParams(str)` | Parses a string containing data parameters into an object. | `str: string` | `parseDataParams("param1:value1;param2:value2")` -> `{ param1: "value1", param2: "value2" }` |
|
|
36
|
-
| `parseCSSUrl(cssUrl)` | Extracts the URL from a CSS `url()` declaration. | `cssUrl: string` | `parseCSSUrl("url('https://example.com/image.jpg')")` -> `https://example.com/image.jpg` |
|
|
37
|
-
| `Observer` | A class for observing elements and triggering callbacks when they intersect with the viewport. | N/A | `const observer = new Observer((target) => { console.log(target); }); observer.observe(element);` |
|
|
38
|
-
| `LazyImgLoader` | A class for lazy loading images. | N/A | `const lazyLoader = new LazyImgLoader(); lazyLoader.lazify(element, image, imageSrc);` |
|
|
39
|
-
| `circularShift(value, max, shift)` | Performs a circular shift on a number. | `value: number`, `max: number = 6`, `shift: number = 1` | `circularShift(5, 10, 2)` -> `7` |
|
|
40
|
-
| `parseDom(html)` | Parses HTML into a DOM element. | `html: string` | `const element = parseDom("<div>Hello</div>");` |
|
|
41
|
-
| `copyAttributes(target, source)` | Copies attributes from one DOM element to another. | `target: HTMLElement`, `source: HTMLElement` | `copyAttributes(targetElement, sourceElement);` |
|
|
42
|
-
| `replaceElementTag(element, tagName)` | Replaces a DOM element with a new element of a different tag. | `element: HTMLElement`, `tagName: string` | `replaceElementTag(element, "span");` |
|
|
43
|
-
| `getAllUniqueParents(elements)` | Gets all unique parent elements of a list of elements. | `elements: HTMLElement[]` | `const parents = getAllUniqueParents(elements);` |
|
|
44
|
-
| `findNextSibling(element)` | Finds the next sibling element of a given element. | `element: HTMLElement` | `const nextSibling = findNextSibling(element);` |
|
|
45
|
-
| `waitForElementExists(parent, selector, callback)` | Waits for an element to exist within a parent element and then calls a callback. | `parent: HTMLElement`, `selector: string`, `callback: (element: HTMLElement) => void` | `waitForElementExists(container, ".target-element", (element) => { ... });` |
|
|
46
|
-
| `watchElementChildrenCount(element, callback)` | Watches for changes in the number of children of an element and calls a callback. | `element: HTMLElement`, `callback: (observer: MutationObserver, count: number) => void` | `watchElementChildrenCount(element, (observer, count) => { ... });` |
|
|
47
|
-
| `watchDomChangesWithThrottle(element, callback, throttle = 1e3, options = { childList: true, subtree: true, attributes: true })` | Watches for DOM changes within an element and calls a callback with throttling. | `element: HTMLElement`, `callback: (mutationList: MutationRecord[]) => void`, `throttle?: number`, `options?: MutationObserverInit` | `watchDomChangesWithThrottle(element, (mutationList) => { ... });` |
|
|
48
|
-
| `downloader(options)` | Creates a download button for a video element. | `options: { button: string, append?: string, after?: string, cbBefore?: () => void }` | `downloader({ button: "#download-button" });` |
|
|
49
|
-
| `MOBILE_UA` | A constant containing a mobile user agent string. | N/A | `console.log(MOBILE_UA);` |
|
|
50
|
-
| `fetchWith(url, options)` | Fetches data from a URL. | `url: string`, `options: { html?: boolean, mobile?: boolean }` | `fetchWith("https://api.example.com/data", { html: true }).then((html) => { ... });` |
|
|
51
|
-
| `fetchHtml(url)` | Fetches HTML from a URL. | `url: string` | `fetchHtml("https://example.com/page.html").then((html) => { ... });` |
|
|
52
|
-
| `fetchText(url)` | Fetches text from a URL. | `url: string` | `fetchText("https://example.com/data.txt").then((text) => { ... });` |
|
|
53
|
-
| `objectToFormData(object)` | Converts an object to FormData. | `object: object` | `const formData = objectToFormData({ name: "John", age: 30 });` |
|
|
54
|
-
| `listenEvents(element, events, callback)` | Adds event listeners to a DOM element. | `element: HTMLElement`, `events: string[]`, `callback: (event: Event) => void` | `listenEvents(element, ["click", "mouseover"], (event) => { ... });` |
|
|
55
|
-
| `Tick(delay, startImmediate = true)` | A class for creating interval timers. | `delay: number`, `startImmediate?: boolean` | `const tick = new Tick(1000, false); tick.start(() => { ... });` |
|
|
56
|
-
| `isMob()` | Checks if the current device is a mobile device. | N/A | `if (isMob()) { ... }` |
|
|
57
|
-
| `computeAsyncOneAtTime(iterable)` | Executes asynchronous functions one at a time. | `iterable: Iterable<() => Promise<any>>` | `computeAsyncOneAtTime(asyncFunctions).then((results) => { ... });` |
|
|
58
|
-
| `wait(milliseconds)` | Waits for a given number of milliseconds. | `milliseconds: number` | `await wait(1000);` |
|
|
59
|
-
| `AsyncPool` | A class for managing asynchronous tasks with priorities. | N/A | `const spool = new AsyncPool(); spool.push(() => { v: () => fetch(...), p: 1 });` |
|
|
60
|
-
| `chunks(arr, n)` | Splits an array into chunks of a given size. | `arr: Array<any>`, `n: number` | `const chunks = chunks([1, 2, 3, 4, 5], 2);` -> `[[1, 2], [3, 4], [5]]` |
|
|
61
|
-
| `range(start, end)` | Creates a range of numbers from `start` to `end` (inclusive). | `start: number`, `end: number` | `const numbers = range(1, 5);` -> `[1, 2, 3, 4, 5]` |
|
|
1
|
+
### _daddy told us not to be ashamed of our utils_
|
|
2
|
+

|
|
3
|
+
|
|
4
|
+
```
|
|
5
|
+
<script src="https://unpkg.com/billy-herrington-utils"></script>
|
|
6
|
+
```
|
|
7
|
+
```
|
|
8
|
+
<script src="https://unpkg.com/billy-herrington-utils/dist/billy-herrington-utils.umd.js"></script>
|
|
9
|
+
<script>
|
|
10
|
+
const { Tick } = window.bhutils;
|
|
11
|
+
</script>
|
|
12
|
+
```
|
|
13
|
+
```
|
|
14
|
+
npm i billy-herrington-utils
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**A comprehensive collection of utility 🛠️ functions to make dungeon life easier.**
|
|
18
|
+
|
|
19
|
+
**Key features:**
|
|
20
|
+
|
|
21
|
+
* **String manipulation:** Easily parse, sanitize, and convert strings.
|
|
22
|
+
* **Time and date:** Work with time and date values effortlessly.
|
|
23
|
+
* **DOM manipulation:** Interact with DOM elements like a pro.
|
|
24
|
+
* **Networking:** Make HTTP requests and handle data with ease.
|
|
25
|
+
* **Miscellaneous:** A variety of other useful functions for common tasks.
|
|
26
|
+
|
|
27
|
+
## **Documentation**
|
|
28
|
+
|
|
29
|
+
| Function | Short Explanation | Input Parameters | Example Input/Output or Usage |
|
|
30
|
+
|---|---|---|---|
|
|
31
|
+
| `stringToWords(s)` | Splits a string into an array of words. | `s: string` | `stringToWords("Hello, world!")` -> `["hello", "world"]` |
|
|
32
|
+
| `sanitizeStr(s)` | Sanitizes a string by removing newlines, tabs, and extra spaces. | `s: string` | `sanitizeStr("Hello\nWorld\t")` -> `hello world` |
|
|
33
|
+
| `timeToSeconds(timeStr)` | Converts a time string to seconds. | `timeStr: string` | `timeToSeconds("1h30m")` -> `5400` |
|
|
34
|
+
| `parseIntegerOr(value, defaultValue)` | Parses a string as an integer. | `value: string`, `defaultValue: number` | `parseIntegerOr("10", 0)` -> `10`, `parseIntegerOr("abc", 0)` -> `0` |
|
|
35
|
+
| `parseDataParams(str)` | Parses a string containing data parameters into an object. | `str: string` | `parseDataParams("param1:value1;param2:value2")` -> `{ param1: "value1", param2: "value2" }` |
|
|
36
|
+
| `parseCSSUrl(cssUrl)` | Extracts the URL from a CSS `url()` declaration. | `cssUrl: string` | `parseCSSUrl("url('https://example.com/image.jpg')")` -> `https://example.com/image.jpg` |
|
|
37
|
+
| `Observer` | A class for observing elements and triggering callbacks when they intersect with the viewport. | N/A | `const observer = new Observer((target) => { console.log(target); }); observer.observe(element);` |
|
|
38
|
+
| `LazyImgLoader` | A class for lazy loading images. | N/A | `const lazyLoader = new LazyImgLoader(); lazyLoader.lazify(element, image, imageSrc);` |
|
|
39
|
+
| `circularShift(value, max, shift)` | Performs a circular shift on a number. | `value: number`, `max: number = 6`, `shift: number = 1` | `circularShift(5, 10, 2)` -> `7` |
|
|
40
|
+
| `parseDom(html)` | Parses HTML into a DOM element. | `html: string` | `const element = parseDom("<div>Hello</div>");` |
|
|
41
|
+
| `copyAttributes(target, source)` | Copies attributes from one DOM element to another. | `target: HTMLElement`, `source: HTMLElement` | `copyAttributes(targetElement, sourceElement);` |
|
|
42
|
+
| `replaceElementTag(element, tagName)` | Replaces a DOM element with a new element of a different tag. | `element: HTMLElement`, `tagName: string` | `replaceElementTag(element, "span");` |
|
|
43
|
+
| `getAllUniqueParents(elements)` | Gets all unique parent elements of a list of elements. | `elements: HTMLElement[]` | `const parents = getAllUniqueParents(elements);` |
|
|
44
|
+
| `findNextSibling(element)` | Finds the next sibling element of a given element. | `element: HTMLElement` | `const nextSibling = findNextSibling(element);` |
|
|
45
|
+
| `waitForElementExists(parent, selector, callback)` | Waits for an element to exist within a parent element and then calls a callback. | `parent: HTMLElement`, `selector: string`, `callback: (element: HTMLElement) => void` | `waitForElementExists(container, ".target-element", (element) => { ... });` |
|
|
46
|
+
| `watchElementChildrenCount(element, callback)` | Watches for changes in the number of children of an element and calls a callback. | `element: HTMLElement`, `callback: (observer: MutationObserver, count: number) => void` | `watchElementChildrenCount(element, (observer, count) => { ... });` |
|
|
47
|
+
| `watchDomChangesWithThrottle(element, callback, throttle = 1e3, options = { childList: true, subtree: true, attributes: true })` | Watches for DOM changes within an element and calls a callback with throttling. | `element: HTMLElement`, `callback: (mutationList: MutationRecord[]) => void`, `throttle?: number`, `options?: MutationObserverInit` | `watchDomChangesWithThrottle(element, (mutationList) => { ... });` |
|
|
48
|
+
| `downloader(options)` | Creates a download button for a video element. | `options: { button: string, append?: string, after?: string, cbBefore?: () => void }` | `downloader({ button: "#download-button" });` |
|
|
49
|
+
| `MOBILE_UA` | A constant containing a mobile user agent string. | N/A | `console.log(MOBILE_UA);` |
|
|
50
|
+
| `fetchWith(url, options)` | Fetches data from a URL. | `url: string`, `options: { html?: boolean, mobile?: boolean }` | `fetchWith("https://api.example.com/data", { html: true }).then((html) => { ... });` |
|
|
51
|
+
| `fetchHtml(url)` | Fetches HTML from a URL. | `url: string` | `fetchHtml("https://example.com/page.html").then((html) => { ... });` |
|
|
52
|
+
| `fetchText(url)` | Fetches text from a URL. | `url: string` | `fetchText("https://example.com/data.txt").then((text) => { ... });` |
|
|
53
|
+
| `objectToFormData(object)` | Converts an object to FormData. | `object: object` | `const formData = objectToFormData({ name: "John", age: 30 });` |
|
|
54
|
+
| `listenEvents(element, events, callback)` | Adds event listeners to a DOM element. | `element: HTMLElement`, `events: string[]`, `callback: (event: Event) => void` | `listenEvents(element, ["click", "mouseover"], (event) => { ... });` |
|
|
55
|
+
| `Tick(delay, startImmediate = true)` | A class for creating interval timers. | `delay: number`, `startImmediate?: boolean` | `const tick = new Tick(1000, false); tick.start(() => { ... });` |
|
|
56
|
+
| `isMob()` | Checks if the current device is a mobile device. | N/A | `if (isMob()) { ... }` |
|
|
57
|
+
| `computeAsyncOneAtTime(iterable)` | Executes asynchronous functions one at a time. | `iterable: Iterable<() => Promise<any>>` | `computeAsyncOneAtTime(asyncFunctions).then((results) => { ... });` |
|
|
58
|
+
| `wait(milliseconds)` | Waits for a given number of milliseconds. | `milliseconds: number` | `await wait(1000);` |
|
|
59
|
+
| `AsyncPool` | A class for managing asynchronous tasks with priorities. | N/A | `const spool = new AsyncPool(); spool.push(() => { v: () => fetch(...), p: 1 });` |
|
|
60
|
+
| `chunks(arr, n)` | Splits an array into chunks of a given size. | `arr: Array<any>`, `n: number` | `const chunks = chunks([1, 2, 3, 4, 5], 2);` -> `[[1, 2], [3, 4], [5]]` |
|
|
61
|
+
| `range(start, end)` | Creates a range of numbers from `start` to `end` (inclusive). | `start: number`, `end: number` | `const numbers = range(1, 5);` -> `[1, 2, 3, 4, 5]` |
|
|
@@ -7,8 +7,18 @@ function stringToWords(s) {
|
|
|
7
7
|
function sanitizeStr(s) {
|
|
8
8
|
return s?.replace(/\n|\t/, " ").replace(/ {2,}/, " ").trim().toLowerCase() || "";
|
|
9
9
|
}
|
|
10
|
+
function formatTimeToHHMMSS(timeString) {
|
|
11
|
+
const regex = /(?:(\d+)\s*h\s*)?(?:(\d+)\s*mi?n?\s*)?(?:(\d+)\s*sec)?/;
|
|
12
|
+
const match = timeString.match(regex);
|
|
13
|
+
const h = parseInt(match?.[1] || "0");
|
|
14
|
+
const m = parseInt(match?.[2] || "0");
|
|
15
|
+
const s = parseInt(match?.[3] || "0");
|
|
16
|
+
const pad = (num) => String(num).padStart(2, "0");
|
|
17
|
+
return `${pad(h)}:${pad(m)}:${pad(s)}`;
|
|
18
|
+
}
|
|
10
19
|
function timeToSeconds(t) {
|
|
11
|
-
|
|
20
|
+
const r = /sec|min|h|m/.test(t) ? formatTimeToHHMMSS(t) : t;
|
|
21
|
+
return (r?.match(/\d+/gm) || [0]).reverse().map((s, i) => parseInt(s) * 60 ** i).reduce((a, b) => a + b);
|
|
12
22
|
}
|
|
13
23
|
function parseIntegerOr(n, or) {
|
|
14
24
|
return ((num) => Number.isNaN(num) ? or : num)(parseInt(n));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"billy-herrington-utils.es.js","sources":["../src/utils/strings/index.ts","../src/utils/parsers/index.ts","../src/utils/observers/index.ts","../src/utils/math/index.ts","../src/utils/dom/index.ts","../src/utils/fetch/index.ts","../src/utils/events/index.ts","../src/utils/device/index.ts","../src/utils/async/index.ts","../src/utils/arrays/index.ts"],"sourcesContent":["export function stringToWords(s: string): Array<string> {\r\n return s.split(\",\").map(s => s.trim().toLowerCase()).filter(_ => _);\r\n}\r\n\r\nexport function sanitizeStr(s: string) {\r\n return s?.replace(/\\n|\\t/, ' ').replace(/ {2,}/, ' ').trim().toLowerCase() || \"\";\r\n}\r\n","export function timeToSeconds(t: string): number {\r\n return (t?.match(/\\d+/gm) || [0])\r\n .reverse()\r\n .map((s, i) => parseInt(s as string) * 60 ** i)\r\n .reduce((a, b) => a + b);\r\n}\r\n\r\nexport function parseIntegerOr(n: string | number, or: number): number {\r\n return (num => Number.isNaN(num) ? or : num)(parseInt(n as string));\r\n}\r\n\r\n// \"data:02;body+head:async;void:;zero:;\"\r\nexport function parseDataParams(str: string): Record<string, string> {\r\n return str.split(';').reduce((acc, s) => {\r\n const parsed = s.match(/([\\+\\w]+):(\\w+)?/);\r\n if (parsed) {\r\n const [, key, value] = parsed;\r\n if (value) {\r\n key.split('+').forEach(p => { acc[p] = value; });\r\n }\r\n }\r\n return acc;\r\n }, {} as Record<string, string>);\r\n}\r\n\r\nexport function parseCSSUrl(s: string) {\r\n return s.replace(/url\\(\"|\\\"\\).*/g, '');\r\n}\r\n","export class Observer {\r\n public observer: IntersectionObserver;\r\n constructor(private callback: (entry: Element) => void) {\r\n this.observer = new IntersectionObserver(this.handleIntersection.bind(this));\r\n }\r\n\r\n observe(target: Element) {\r\n this.observer.observe(target);\r\n }\r\n\r\n throttle(target: Element, throttleTime: number) {\r\n this.observer.unobserve(target);\r\n setTimeout(() => this.observer.observe(target), throttleTime);\r\n }\r\n\r\n handleIntersection(entries: Iterable<IntersectionObserverEntry>) {\r\n for (const entry of entries) {\r\n if (entry.isIntersecting) {\r\n this.callback(entry.target);\r\n }\r\n }\r\n }\r\n\r\n static observeWhile(target: Element, callback: () => Promise<boolean> | boolean, throttleTime: number) {\r\n const observer_ = new Observer(async (target: Element) => {\r\n const condition = await callback();\r\n if (condition) observer_.throttle(target, throttleTime);\r\n });\r\n observer_.observe(target);\r\n return observer_;\r\n }\r\n}\r\n\r\nexport class LazyImgLoader {\r\n public lazyImgObserver: Observer;\r\n private attributeName = 'data-lazy-load';\r\n\r\n constructor(shouldDelazify: (target: Element) => boolean) {\r\n this.lazyImgObserver = new Observer((target: Element) => {\r\n if (shouldDelazify(target)) {\r\n this.delazify(target as HTMLImageElement);\r\n }\r\n });\r\n }\r\n\r\n lazify(_target: Element, img: HTMLImageElement, imgSrc: string) {\r\n if (!img || !imgSrc) return;\r\n img.setAttribute(this.attributeName, imgSrc);\r\n img.src = '';\r\n this.lazyImgObserver.observe(img);\r\n }\r\n\r\n delazify = (target: HTMLImageElement) => {\r\n this.lazyImgObserver.observer.unobserve(target);\r\n target.src = target.getAttribute(this.attributeName) as string;\r\n target.removeAttribute(this.attributeName);\r\n }\r\n}\r\n","export function circularShift(n: number, c = 6, s = 1): number {\r\n return (n + s) % c || c;\r\n}\r\n","export function parseDom(html: string): HTMLElement {\r\n const parsed = new DOMParser().parseFromString(html, 'text/html').body;\r\n return parsed.children.length > 1 ? parsed : parsed.firstElementChild as HTMLElement;\r\n}\r\n\r\nexport function copyAttributes(target: HTMLElement | Element, source: HTMLElement | Element) {\r\n for (const attr of source.attributes) {\r\n attr.nodeValue && target.setAttribute(attr.nodeName, attr.nodeValue);\r\n }\r\n}\r\n\r\nexport function replaceElementTag(e: HTMLElement | Element, tagName: string) {\r\n const newTagElement = document.createElement(tagName);\r\n copyAttributes(newTagElement, e);\r\n newTagElement.innerHTML = e.innerHTML;\r\n e.parentNode?.replaceChild(newTagElement, e);\r\n return newTagElement;\r\n}\r\n\r\nexport function getAllUniqueParents(elements: HTMLCollection): Array<HTMLElement | Element> {\r\n return Array.from(elements).reduce((acc, v) => {\r\n if (v.parentElement && !acc.includes(v.parentElement as HTMLElement)) { acc.push(v.parentElement); }\r\n return acc;\r\n }, [] as Array<HTMLElement | Element>);\r\n}\r\n\r\nexport function findNextSibling(el: HTMLElement | Element) {\r\n if (el.nextElementSibling) return el.nextElementSibling;\r\n if (el.parentElement) return findNextSibling(el.parentElement);\r\n return null;\r\n}\r\n\r\nexport function waitForElementExists(parent: HTMLElement | Element, selector: string, callback: (el: Element) => void): void {\r\n const observer = new MutationObserver((_mutations) => {\r\n const el = parent.querySelector(selector);\r\n if (el) {\r\n observer.disconnect();\r\n callback(el);\r\n }\r\n });\r\n observer.observe(document.body, { childList: true, subtree: true });\r\n}\r\n\r\nexport function watchElementChildrenCount(element: HTMLElement | Element,\r\n callback: (observer: MutationObserver, count: number) => void): void {\r\n let count = element.children.length;\r\n const observer = new MutationObserver((mutationList, observer) => {\r\n for (const mutation of mutationList) {\r\n if (mutation.type === \"childList\") {\r\n if (count !== element.children.length) {\r\n count = element.children.length;\r\n callback(observer, count);\r\n }\r\n }\r\n }\r\n });\r\n observer.observe(element, { childList: true });\r\n}\r\n\r\nexport function watchDomChangesWithThrottle(element: HTMLElement | Element, callback: () => void,\r\n throttle = 1000, options: Record<string, boolean> = { childList: true, subtree: true, attributes: true }) {\r\n let lastMutationTime: number;\r\n let timeout: number;\r\n const observer = new MutationObserver((_mutationList, _observer) => {\r\n const now = Date.now();\r\n if (lastMutationTime && now - lastMutationTime < throttle) {\r\n timeout && clearTimeout(timeout);\r\n }\r\n timeout = setTimeout(callback, throttle);\r\n lastMutationTime = now;\r\n });\r\n observer.observe(element, options);\r\n}\r\n\r\nexport function downloader(options = { append: \"\", after: \"\", button: \"\", cbBefore: () => { } }) {\r\n const btn = parseDom(options.button);\r\n\r\n if (options.append) document.querySelector(options.append)?.append(btn);\r\n if (options.after) document.querySelector(options.after)?.after(btn);\r\n\r\n btn.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n\r\n if (options.cbBefore) options.cbBefore();\r\n\r\n waitForElementExists(document.body, 'video', (video: Element) => {\r\n window.location.href = video.getAttribute('src') as string;\r\n });\r\n });\r\n}","import { parseDom } from \"../dom\";\r\n\r\nexport const MOBILE_UA = [\r\n 'Mozilla/5.0 (Linux; Android 10; K)',\r\n 'AppleWebKit/537.36 (KHTML, like Gecko)',\r\n 'Chrome/114.0.0.0 Mobile Safari/537.36'].join(' ');\r\n\r\nexport function fetchWith(url: string, options: Record<string, boolean> = { html: false, mobile: false }) {\r\n const reqOpts = {};\r\n if (options.mobile) Object.assign(reqOpts, { headers: new Headers({ \"User-Agent\": MOBILE_UA }) });\r\n return fetch(url, reqOpts).then((r) => r.text()).then(r => options.html ? parseDom(r) : r);\r\n}\r\n\r\nexport const fetchHtml = (url: string) => fetchWith(url, { html: true });\r\n\r\nexport const fetchText = (url: string) => fetchWith(url);\r\n\r\nexport function objectToFormData(object: Record<string, number | boolean | string>): FormData {\r\n const formData = new FormData();\r\n Object.entries(object).forEach(([k, v]) => formData.append(k, v as string));\r\n return formData;\r\n}\r\n","export function listenEvents(dom: HTMLElement | Element, events: Array<string>, callback: (e: Event) => void): void {\r\n for (const e of events) {\r\n dom.addEventListener(e, callback, true);\r\n }\r\n}\r\n\r\nexport class Tick {\r\n private tick?: number;\r\n private callbackFinal?: () => void;\r\n\r\n constructor(private delay: number, private startImmediate: boolean = true) {}\r\n\r\n public start(callback: () => void, callbackFinal?: () => void): void {\r\n this.stop();\r\n this.callbackFinal = callbackFinal;\r\n if (this.startImmediate) callback();\r\n this.tick = window.setInterval(callback, this.delay);\r\n }\r\n\r\n public stop(): void {\r\n if (this.tick !== undefined) {\r\n clearInterval(this.tick);\r\n this.tick = undefined;\r\n }\r\n if (this.callbackFinal) {\r\n this.callbackFinal();\r\n this.callbackFinal = undefined;\r\n }\r\n }\r\n}\r\n","export function isMob() {\r\n return /iPhone|Android/i.test(navigator.userAgent);\r\n}","// https://2ality.com/2016/10/asynchronous-iteration.html\r\nexport async function computeAsyncOneAtTime(iterable: Iterable<() => Promise<void>>) {\r\n const res = [];\r\n for await (const f of iterable) {\r\n res.push(await f());\r\n }\r\n return res;\r\n}\r\n\r\nexport function wait(milliseconds: number) {\r\n return new Promise((resolve) => setTimeout(resolve, milliseconds));\r\n}\r\n\r\ninterface AsyncPoolTask {\r\n v: () => Promise<void>;\r\n p: number;\r\n}\r\n\r\nexport class AsyncPool {\r\n private cur = 0;\r\n private finished: Promise<boolean>;\r\n private _resolve?: (value: boolean | PromiseLike<boolean>) => void;\r\n\r\n public static async doNAsyncAtOnce(max = 1, pool: Array<AsyncPoolTask | (() => Promise<void>)> = []) {\r\n const spool = new AsyncPool(max);\r\n pool.forEach(f => spool.push(f));\r\n return spool.run();\r\n }\r\n\r\n constructor(private max = 1, private pool: Array<AsyncPoolTask> = []) {\r\n this.finished = new Promise((resolve) => {\r\n this._resolve = resolve;\r\n });\r\n }\r\n\r\n private getHighPriorityFirst(p = 0): (() => Promise<void>) | undefined {\r\n if (p > 3 || this.pool.length === 0) return undefined;\r\n const i = this.pool.findIndex((e) => e.p === p);\r\n if (i >= 0) {\r\n const res = this.pool[i].v;\r\n this.pool.splice(i, 1);\r\n return res;\r\n }\r\n return this.getHighPriorityFirst(p + 1);\r\n }\r\n\r\n private async runTask() {\r\n this.cur++;\r\n const f = this.getHighPriorityFirst();\r\n await f?.();\r\n this.cur--;\r\n this.runTasks();\r\n }\r\n\r\n private runTasks() {\r\n if (!this.pool.length) {\r\n this._resolve?.(true);\r\n return;\r\n }\r\n if (this.cur < this.max) {\r\n this.runTask();\r\n this.runTasks();\r\n }\r\n }\r\n\r\n public async run() {\r\n this.runTasks();\r\n return this.finished;\r\n }\r\n\r\n public push(x: AsyncPoolTask | (() => Promise<void>)) {\r\n this.pool.push('p' in x ? x : { v: x, p: 0 });\r\n }\r\n}\r\n\r\n","export function chunks<T>(arr: Array<T>, n: number): Array<Array<T>> {\r\n return Array.from({ length: Math.ceil(arr.length / n) }, (_, i) => arr.slice(i * n, i * n + n));\r\n}\r\n\r\nexport function range(size: number, startAt: number = 1, step: number = 1): number[] {\r\n return Array.from({ length: size }, (_, index) => startAt + index * step);\r\n}\r\n"],"names":["s","target","observer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"billy-herrington-utils.es.js","sources":["../src/utils/strings/index.ts","../src/utils/parsers/index.ts","../src/utils/observers/index.ts","../src/utils/math/index.ts","../src/utils/dom/index.ts","../src/utils/fetch/index.ts","../src/utils/events/index.ts","../src/utils/device/index.ts","../src/utils/async/index.ts","../src/utils/arrays/index.ts"],"sourcesContent":["export function stringToWords(s: string): Array<string> {\n return s.split(\",\").map(s => s.trim().toLowerCase()).filter(_ => _);\n}\n\nexport function sanitizeStr(s: string) {\n return s?.replace(/\\n|\\t/, ' ').replace(/ {2,}/, ' ').trim().toLowerCase() || \"\";\n}\n","export function formatTimeToHHMMSS(timeString: string): string {\n const regex: RegExp = /(?:(\\d+)\\s*h\\s*)?(?:(\\d+)\\s*mi?n?\\s*)?(?:(\\d+)\\s*sec)?/;\n const match: RegExpMatchArray | null = timeString.match(regex);\n const h: number = parseInt(match?.[1] || '0');\n const m: number = parseInt(match?.[2] || '0');\n const s: number = parseInt(match?.[3] || '0');\n const pad = (num: number): string => String(num).padStart(2, '0');\n return `${pad(h)}:${pad(m)}:${pad(s)}`;\n}\n\n// \"01:22:03\" -> 4923\nexport function timeToSeconds(t: string): number {\n const r = /sec|min|h|m/.test(t) ? formatTimeToHHMMSS(t) : t;\n return (r?.match(/\\d+/gm) || [0])\n .reverse()\n .map((s, i) => parseInt(s as string) * 60 ** i)\n .reduce((a, b) => a + b);\n}\n\nexport function parseIntegerOr(n: string | number, or: number): number {\n return (num => Number.isNaN(num) ? or : num)(parseInt(n as string));\n}\n\n// \"data:02;body+head:async;void:;zero:;\"\nexport function parseDataParams(str: string): Record<string, string> {\n return str.split(';').reduce((acc, s) => {\n const parsed = s.match(/([\\+\\w]+):(\\w+)?/);\n if (parsed) {\n const [, key, value] = parsed;\n if (value) {\n key.split('+').forEach(p => { acc[p] = value; });\n }\n }\n return acc;\n }, {} as Record<string, string>);\n}\n\nexport function parseCSSUrl(s: string) {\n return s.replace(/url\\(\"|\\\"\\).*/g, '');\n}\n","export class Observer {\n public observer: IntersectionObserver;\n constructor(private callback: (entry: Element) => void) {\n this.observer = new IntersectionObserver(this.handleIntersection.bind(this));\n }\n\n observe(target: Element) {\n this.observer.observe(target);\n }\n\n throttle(target: Element, throttleTime: number) {\n this.observer.unobserve(target);\n setTimeout(() => this.observer.observe(target), throttleTime);\n }\n\n handleIntersection(entries: Iterable<IntersectionObserverEntry>) {\n for (const entry of entries) {\n if (entry.isIntersecting) {\n this.callback(entry.target);\n }\n }\n }\n\n static observeWhile(target: Element, callback: () => Promise<boolean> | boolean, throttleTime: number) {\n const observer_ = new Observer(async (target: Element) => {\n const condition = await callback();\n if (condition) observer_.throttle(target, throttleTime);\n });\n observer_.observe(target);\n return observer_;\n }\n}\n\nexport class LazyImgLoader {\n public lazyImgObserver: Observer;\n private attributeName = 'data-lazy-load';\n\n constructor(shouldDelazify: (target: Element) => boolean) {\n this.lazyImgObserver = new Observer((target: Element) => {\n if (shouldDelazify(target)) {\n this.delazify(target as HTMLImageElement);\n }\n });\n }\n\n lazify(_target: Element, img: HTMLImageElement, imgSrc: string) {\n if (!img || !imgSrc) return;\n img.setAttribute(this.attributeName, imgSrc);\n img.src = '';\n this.lazyImgObserver.observe(img);\n }\n\n delazify = (target: HTMLImageElement) => {\n this.lazyImgObserver.observer.unobserve(target);\n target.src = target.getAttribute(this.attributeName) as string;\n target.removeAttribute(this.attributeName);\n }\n}\n","export function circularShift(n: number, c = 6, s = 1): number {\n return (n + s) % c || c;\n}\n","export function parseDom(html: string): HTMLElement {\n const parsed = new DOMParser().parseFromString(html, 'text/html').body;\n return parsed.children.length > 1 ? parsed : parsed.firstElementChild as HTMLElement;\n}\n\nexport function copyAttributes(target: HTMLElement | Element, source: HTMLElement | Element) {\n for (const attr of source.attributes) {\n attr.nodeValue && target.setAttribute(attr.nodeName, attr.nodeValue);\n }\n}\n\nexport function replaceElementTag(e: HTMLElement | Element, tagName: string) {\n const newTagElement = document.createElement(tagName);\n copyAttributes(newTagElement, e);\n newTagElement.innerHTML = e.innerHTML;\n e.parentNode?.replaceChild(newTagElement, e);\n return newTagElement;\n}\n\nexport function getAllUniqueParents(elements: HTMLCollection): Array<HTMLElement | Element> {\n return Array.from(elements).reduce((acc, v) => {\n if (v.parentElement && !acc.includes(v.parentElement as HTMLElement)) { acc.push(v.parentElement); }\n return acc;\n }, [] as Array<HTMLElement | Element>);\n}\n\nexport function findNextSibling(el: HTMLElement | Element) {\n if (el.nextElementSibling) return el.nextElementSibling;\n if (el.parentElement) return findNextSibling(el.parentElement);\n return null;\n}\n\nexport function waitForElementExists(parent: HTMLElement | Element, selector: string, callback: (el: Element) => void): void {\n const observer = new MutationObserver((_mutations) => {\n const el = parent.querySelector(selector);\n if (el) {\n observer.disconnect();\n callback(el);\n }\n });\n observer.observe(document.body, { childList: true, subtree: true });\n}\n\nexport function watchElementChildrenCount(element: HTMLElement | Element,\n callback: (observer: MutationObserver, count: number) => void): void {\n let count = element.children.length;\n const observer = new MutationObserver((mutationList, observer) => {\n for (const mutation of mutationList) {\n if (mutation.type === \"childList\") {\n if (count !== element.children.length) {\n count = element.children.length;\n callback(observer, count);\n }\n }\n }\n });\n observer.observe(element, { childList: true });\n}\n\nexport function watchDomChangesWithThrottle(element: HTMLElement | Element, callback: () => void,\n throttle = 1000, options: Record<string, boolean> = { childList: true, subtree: true, attributes: true }) {\n let lastMutationTime: number;\n let timeout: number;\n const observer = new MutationObserver((_mutationList, _observer) => {\n const now = Date.now();\n if (lastMutationTime && now - lastMutationTime < throttle) {\n timeout && clearTimeout(timeout);\n }\n timeout = setTimeout(callback, throttle);\n lastMutationTime = now;\n });\n observer.observe(element, options);\n}\n\nexport function downloader(options = { append: \"\", after: \"\", button: \"\", cbBefore: () => { } }) {\n const btn = parseDom(options.button);\n\n if (options.append) document.querySelector(options.append)?.append(btn);\n if (options.after) document.querySelector(options.after)?.after(btn);\n\n btn.addEventListener('click', (e) => {\n e.preventDefault();\n\n if (options.cbBefore) options.cbBefore();\n\n waitForElementExists(document.body, 'video', (video: Element) => {\n window.location.href = video.getAttribute('src') as string;\n });\n });\n}","import { parseDom } from \"../dom\";\n\nexport const MOBILE_UA = [\n 'Mozilla/5.0 (Linux; Android 10; K)',\n 'AppleWebKit/537.36 (KHTML, like Gecko)',\n 'Chrome/114.0.0.0 Mobile Safari/537.36'].join(' ');\n\nexport function fetchWith(url: string, options: Record<string, boolean> = { html: false, mobile: false }) {\n const reqOpts = {};\n if (options.mobile) Object.assign(reqOpts, { headers: new Headers({ \"User-Agent\": MOBILE_UA }) });\n return fetch(url, reqOpts).then((r) => r.text()).then(r => options.html ? parseDom(r) : r);\n}\n\nexport const fetchHtml = (url: string) => fetchWith(url, { html: true });\n\nexport const fetchText = (url: string) => fetchWith(url);\n\nexport function objectToFormData(object: Record<string, number | boolean | string>): FormData {\n const formData = new FormData();\n Object.entries(object).forEach(([k, v]) => formData.append(k, v as string));\n return formData;\n}\n","export function listenEvents(dom: HTMLElement | Element, events: Array<string>, callback: (e: Event) => void): void {\n for (const e of events) {\n dom.addEventListener(e, callback, true);\n }\n}\n\nexport class Tick {\n private tick?: number;\n private callbackFinal?: () => void;\n\n constructor(private delay: number, private startImmediate: boolean = true) {}\n\n public start(callback: () => void, callbackFinal?: () => void): void {\n this.stop();\n this.callbackFinal = callbackFinal;\n if (this.startImmediate) callback();\n this.tick = window.setInterval(callback, this.delay);\n }\n\n public stop(): void {\n if (this.tick !== undefined) {\n clearInterval(this.tick);\n this.tick = undefined;\n }\n if (this.callbackFinal) {\n this.callbackFinal();\n this.callbackFinal = undefined;\n }\n }\n}\n","export function isMob() {\n return /iPhone|Android/i.test(navigator.userAgent);\n}","// https://2ality.com/2016/10/asynchronous-iteration.html\nexport async function computeAsyncOneAtTime(iterable: Iterable<() => Promise<void>>) {\n const res = [];\n for await (const f of iterable) {\n res.push(await f());\n }\n return res;\n}\n\nexport function wait(milliseconds: number) {\n return new Promise((resolve) => setTimeout(resolve, milliseconds));\n}\n\ninterface AsyncPoolTask {\n v: () => Promise<void>;\n p: number;\n}\n\nexport class AsyncPool {\n private cur = 0;\n private finished: Promise<boolean>;\n private _resolve?: (value: boolean | PromiseLike<boolean>) => void;\n\n public static async doNAsyncAtOnce(max = 1, pool: Array<AsyncPoolTask | (() => Promise<void>)> = []) {\n const spool = new AsyncPool(max);\n pool.forEach(f => spool.push(f));\n return spool.run();\n }\n\n constructor(private max = 1, private pool: Array<AsyncPoolTask> = []) {\n this.finished = new Promise((resolve) => {\n this._resolve = resolve;\n });\n }\n\n private getHighPriorityFirst(p = 0): (() => Promise<void>) | undefined {\n if (p > 3 || this.pool.length === 0) return undefined;\n const i = this.pool.findIndex((e) => e.p === p);\n if (i >= 0) {\n const res = this.pool[i].v;\n this.pool.splice(i, 1);\n return res;\n }\n return this.getHighPriorityFirst(p + 1);\n }\n\n private async runTask() {\n this.cur++;\n const f = this.getHighPriorityFirst();\n await f?.();\n this.cur--;\n this.runTasks();\n }\n\n private runTasks() {\n if (!this.pool.length) {\n this._resolve?.(true);\n return;\n }\n if (this.cur < this.max) {\n this.runTask();\n this.runTasks();\n }\n }\n\n public async run() {\n this.runTasks();\n return this.finished;\n }\n\n public push(x: AsyncPoolTask | (() => Promise<void>)) {\n this.pool.push('p' in x ? x : { v: x, p: 0 });\n }\n}\n\n","export function chunks<T>(arr: Array<T>, n: number): Array<Array<T>> {\n return Array.from({ length: Math.ceil(arr.length / n) }, (_, i) => arr.slice(i * n, i * n + n));\n}\n\nexport function range(size: number, startAt: number = 1, step: number = 1): number[] {\n return Array.from({ length: size }, (_, index) => startAt + index * step);\n}\n"],"names":["s","target","observer"],"mappings":"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"}
|
|
@@ -11,8 +11,18 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
11
11
|
function sanitizeStr(s) {
|
|
12
12
|
return s?.replace(/\n|\t/, " ").replace(/ {2,}/, " ").trim().toLowerCase() || "";
|
|
13
13
|
}
|
|
14
|
+
function formatTimeToHHMMSS(timeString) {
|
|
15
|
+
const regex = /(?:(\d+)\s*h\s*)?(?:(\d+)\s*mi?n?\s*)?(?:(\d+)\s*sec)?/;
|
|
16
|
+
const match = timeString.match(regex);
|
|
17
|
+
const h = parseInt(match?.[1] || "0");
|
|
18
|
+
const m = parseInt(match?.[2] || "0");
|
|
19
|
+
const s = parseInt(match?.[3] || "0");
|
|
20
|
+
const pad = (num) => String(num).padStart(2, "0");
|
|
21
|
+
return `${pad(h)}:${pad(m)}:${pad(s)}`;
|
|
22
|
+
}
|
|
14
23
|
function timeToSeconds(t) {
|
|
15
|
-
|
|
24
|
+
const r = /sec|min|h|m/.test(t) ? formatTimeToHHMMSS(t) : t;
|
|
25
|
+
return (r?.match(/\d+/gm) || [0]).reverse().map((s, i) => parseInt(s) * 60 ** i).reduce((a, b) => a + b);
|
|
16
26
|
}
|
|
17
27
|
function parseIntegerOr(n, or) {
|
|
18
28
|
return ((num) => Number.isNaN(num) ? or : num)(parseInt(n));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"billy-herrington-utils.umd.js","sources":["../src/utils/strings/index.ts","../src/utils/parsers/index.ts","../src/utils/observers/index.ts","../src/utils/math/index.ts","../src/utils/dom/index.ts","../src/utils/fetch/index.ts","../src/utils/events/index.ts","../src/utils/device/index.ts","../src/utils/async/index.ts","../src/utils/arrays/index.ts"],"sourcesContent":["export function stringToWords(s: string): Array<string> {\r\n return s.split(\",\").map(s => s.trim().toLowerCase()).filter(_ => _);\r\n}\r\n\r\nexport function sanitizeStr(s: string) {\r\n return s?.replace(/\\n|\\t/, ' ').replace(/ {2,}/, ' ').trim().toLowerCase() || \"\";\r\n}\r\n","export function timeToSeconds(t: string): number {\r\n return (t?.match(/\\d+/gm) || [0])\r\n .reverse()\r\n .map((s, i) => parseInt(s as string) * 60 ** i)\r\n .reduce((a, b) => a + b);\r\n}\r\n\r\nexport function parseIntegerOr(n: string | number, or: number): number {\r\n return (num => Number.isNaN(num) ? or : num)(parseInt(n as string));\r\n}\r\n\r\n// \"data:02;body+head:async;void:;zero:;\"\r\nexport function parseDataParams(str: string): Record<string, string> {\r\n return str.split(';').reduce((acc, s) => {\r\n const parsed = s.match(/([\\+\\w]+):(\\w+)?/);\r\n if (parsed) {\r\n const [, key, value] = parsed;\r\n if (value) {\r\n key.split('+').forEach(p => { acc[p] = value; });\r\n }\r\n }\r\n return acc;\r\n }, {} as Record<string, string>);\r\n}\r\n\r\nexport function parseCSSUrl(s: string) {\r\n return s.replace(/url\\(\"|\\\"\\).*/g, '');\r\n}\r\n","export class Observer {\r\n public observer: IntersectionObserver;\r\n constructor(private callback: (entry: Element) => void) {\r\n this.observer = new IntersectionObserver(this.handleIntersection.bind(this));\r\n }\r\n\r\n observe(target: Element) {\r\n this.observer.observe(target);\r\n }\r\n\r\n throttle(target: Element, throttleTime: number) {\r\n this.observer.unobserve(target);\r\n setTimeout(() => this.observer.observe(target), throttleTime);\r\n }\r\n\r\n handleIntersection(entries: Iterable<IntersectionObserverEntry>) {\r\n for (const entry of entries) {\r\n if (entry.isIntersecting) {\r\n this.callback(entry.target);\r\n }\r\n }\r\n }\r\n\r\n static observeWhile(target: Element, callback: () => Promise<boolean> | boolean, throttleTime: number) {\r\n const observer_ = new Observer(async (target: Element) => {\r\n const condition = await callback();\r\n if (condition) observer_.throttle(target, throttleTime);\r\n });\r\n observer_.observe(target);\r\n return observer_;\r\n }\r\n}\r\n\r\nexport class LazyImgLoader {\r\n public lazyImgObserver: Observer;\r\n private attributeName = 'data-lazy-load';\r\n\r\n constructor(shouldDelazify: (target: Element) => boolean) {\r\n this.lazyImgObserver = new Observer((target: Element) => {\r\n if (shouldDelazify(target)) {\r\n this.delazify(target as HTMLImageElement);\r\n }\r\n });\r\n }\r\n\r\n lazify(_target: Element, img: HTMLImageElement, imgSrc: string) {\r\n if (!img || !imgSrc) return;\r\n img.setAttribute(this.attributeName, imgSrc);\r\n img.src = '';\r\n this.lazyImgObserver.observe(img);\r\n }\r\n\r\n delazify = (target: HTMLImageElement) => {\r\n this.lazyImgObserver.observer.unobserve(target);\r\n target.src = target.getAttribute(this.attributeName) as string;\r\n target.removeAttribute(this.attributeName);\r\n }\r\n}\r\n","export function circularShift(n: number, c = 6, s = 1): number {\r\n return (n + s) % c || c;\r\n}\r\n","export function parseDom(html: string): HTMLElement {\r\n const parsed = new DOMParser().parseFromString(html, 'text/html').body;\r\n return parsed.children.length > 1 ? parsed : parsed.firstElementChild as HTMLElement;\r\n}\r\n\r\nexport function copyAttributes(target: HTMLElement | Element, source: HTMLElement | Element) {\r\n for (const attr of source.attributes) {\r\n attr.nodeValue && target.setAttribute(attr.nodeName, attr.nodeValue);\r\n }\r\n}\r\n\r\nexport function replaceElementTag(e: HTMLElement | Element, tagName: string) {\r\n const newTagElement = document.createElement(tagName);\r\n copyAttributes(newTagElement, e);\r\n newTagElement.innerHTML = e.innerHTML;\r\n e.parentNode?.replaceChild(newTagElement, e);\r\n return newTagElement;\r\n}\r\n\r\nexport function getAllUniqueParents(elements: HTMLCollection): Array<HTMLElement | Element> {\r\n return Array.from(elements).reduce((acc, v) => {\r\n if (v.parentElement && !acc.includes(v.parentElement as HTMLElement)) { acc.push(v.parentElement); }\r\n return acc;\r\n }, [] as Array<HTMLElement | Element>);\r\n}\r\n\r\nexport function findNextSibling(el: HTMLElement | Element) {\r\n if (el.nextElementSibling) return el.nextElementSibling;\r\n if (el.parentElement) return findNextSibling(el.parentElement);\r\n return null;\r\n}\r\n\r\nexport function waitForElementExists(parent: HTMLElement | Element, selector: string, callback: (el: Element) => void): void {\r\n const observer = new MutationObserver((_mutations) => {\r\n const el = parent.querySelector(selector);\r\n if (el) {\r\n observer.disconnect();\r\n callback(el);\r\n }\r\n });\r\n observer.observe(document.body, { childList: true, subtree: true });\r\n}\r\n\r\nexport function watchElementChildrenCount(element: HTMLElement | Element,\r\n callback: (observer: MutationObserver, count: number) => void): void {\r\n let count = element.children.length;\r\n const observer = new MutationObserver((mutationList, observer) => {\r\n for (const mutation of mutationList) {\r\n if (mutation.type === \"childList\") {\r\n if (count !== element.children.length) {\r\n count = element.children.length;\r\n callback(observer, count);\r\n }\r\n }\r\n }\r\n });\r\n observer.observe(element, { childList: true });\r\n}\r\n\r\nexport function watchDomChangesWithThrottle(element: HTMLElement | Element, callback: () => void,\r\n throttle = 1000, options: Record<string, boolean> = { childList: true, subtree: true, attributes: true }) {\r\n let lastMutationTime: number;\r\n let timeout: number;\r\n const observer = new MutationObserver((_mutationList, _observer) => {\r\n const now = Date.now();\r\n if (lastMutationTime && now - lastMutationTime < throttle) {\r\n timeout && clearTimeout(timeout);\r\n }\r\n timeout = setTimeout(callback, throttle);\r\n lastMutationTime = now;\r\n });\r\n observer.observe(element, options);\r\n}\r\n\r\nexport function downloader(options = { append: \"\", after: \"\", button: \"\", cbBefore: () => { } }) {\r\n const btn = parseDom(options.button);\r\n\r\n if (options.append) document.querySelector(options.append)?.append(btn);\r\n if (options.after) document.querySelector(options.after)?.after(btn);\r\n\r\n btn.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n\r\n if (options.cbBefore) options.cbBefore();\r\n\r\n waitForElementExists(document.body, 'video', (video: Element) => {\r\n window.location.href = video.getAttribute('src') as string;\r\n });\r\n });\r\n}","import { parseDom } from \"../dom\";\r\n\r\nexport const MOBILE_UA = [\r\n 'Mozilla/5.0 (Linux; Android 10; K)',\r\n 'AppleWebKit/537.36 (KHTML, like Gecko)',\r\n 'Chrome/114.0.0.0 Mobile Safari/537.36'].join(' ');\r\n\r\nexport function fetchWith(url: string, options: Record<string, boolean> = { html: false, mobile: false }) {\r\n const reqOpts = {};\r\n if (options.mobile) Object.assign(reqOpts, { headers: new Headers({ \"User-Agent\": MOBILE_UA }) });\r\n return fetch(url, reqOpts).then((r) => r.text()).then(r => options.html ? parseDom(r) : r);\r\n}\r\n\r\nexport const fetchHtml = (url: string) => fetchWith(url, { html: true });\r\n\r\nexport const fetchText = (url: string) => fetchWith(url);\r\n\r\nexport function objectToFormData(object: Record<string, number | boolean | string>): FormData {\r\n const formData = new FormData();\r\n Object.entries(object).forEach(([k, v]) => formData.append(k, v as string));\r\n return formData;\r\n}\r\n","export function listenEvents(dom: HTMLElement | Element, events: Array<string>, callback: (e: Event) => void): void {\r\n for (const e of events) {\r\n dom.addEventListener(e, callback, true);\r\n }\r\n}\r\n\r\nexport class Tick {\r\n private tick?: number;\r\n private callbackFinal?: () => void;\r\n\r\n constructor(private delay: number, private startImmediate: boolean = true) {}\r\n\r\n public start(callback: () => void, callbackFinal?: () => void): void {\r\n this.stop();\r\n this.callbackFinal = callbackFinal;\r\n if (this.startImmediate) callback();\r\n this.tick = window.setInterval(callback, this.delay);\r\n }\r\n\r\n public stop(): void {\r\n if (this.tick !== undefined) {\r\n clearInterval(this.tick);\r\n this.tick = undefined;\r\n }\r\n if (this.callbackFinal) {\r\n this.callbackFinal();\r\n this.callbackFinal = undefined;\r\n }\r\n }\r\n}\r\n","export function isMob() {\r\n return /iPhone|Android/i.test(navigator.userAgent);\r\n}","// https://2ality.com/2016/10/asynchronous-iteration.html\r\nexport async function computeAsyncOneAtTime(iterable: Iterable<() => Promise<void>>) {\r\n const res = [];\r\n for await (const f of iterable) {\r\n res.push(await f());\r\n }\r\n return res;\r\n}\r\n\r\nexport function wait(milliseconds: number) {\r\n return new Promise((resolve) => setTimeout(resolve, milliseconds));\r\n}\r\n\r\ninterface AsyncPoolTask {\r\n v: () => Promise<void>;\r\n p: number;\r\n}\r\n\r\nexport class AsyncPool {\r\n private cur = 0;\r\n private finished: Promise<boolean>;\r\n private _resolve?: (value: boolean | PromiseLike<boolean>) => void;\r\n\r\n public static async doNAsyncAtOnce(max = 1, pool: Array<AsyncPoolTask | (() => Promise<void>)> = []) {\r\n const spool = new AsyncPool(max);\r\n pool.forEach(f => spool.push(f));\r\n return spool.run();\r\n }\r\n\r\n constructor(private max = 1, private pool: Array<AsyncPoolTask> = []) {\r\n this.finished = new Promise((resolve) => {\r\n this._resolve = resolve;\r\n });\r\n }\r\n\r\n private getHighPriorityFirst(p = 0): (() => Promise<void>) | undefined {\r\n if (p > 3 || this.pool.length === 0) return undefined;\r\n const i = this.pool.findIndex((e) => e.p === p);\r\n if (i >= 0) {\r\n const res = this.pool[i].v;\r\n this.pool.splice(i, 1);\r\n return res;\r\n }\r\n return this.getHighPriorityFirst(p + 1);\r\n }\r\n\r\n private async runTask() {\r\n this.cur++;\r\n const f = this.getHighPriorityFirst();\r\n await f?.();\r\n this.cur--;\r\n this.runTasks();\r\n }\r\n\r\n private runTasks() {\r\n if (!this.pool.length) {\r\n this._resolve?.(true);\r\n return;\r\n }\r\n if (this.cur < this.max) {\r\n this.runTask();\r\n this.runTasks();\r\n }\r\n }\r\n\r\n public async run() {\r\n this.runTasks();\r\n return this.finished;\r\n }\r\n\r\n public push(x: AsyncPoolTask | (() => Promise<void>)) {\r\n this.pool.push('p' in x ? x : { v: x, p: 0 });\r\n }\r\n}\r\n\r\n","export function chunks<T>(arr: Array<T>, n: number): Array<Array<T>> {\r\n return Array.from({ length: Math.ceil(arr.length / n) }, (_, i) => arr.slice(i * n, i * n + n));\r\n}\r\n\r\nexport function range(size: number, startAt: number = 1, step: number = 1): number[] {\r\n return Array.from({ length: size }, (_, index) => startAt + index * step);\r\n}\r\n"],"names":["s","target","observer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"billy-herrington-utils.umd.js","sources":["../src/utils/strings/index.ts","../src/utils/parsers/index.ts","../src/utils/observers/index.ts","../src/utils/math/index.ts","../src/utils/dom/index.ts","../src/utils/fetch/index.ts","../src/utils/events/index.ts","../src/utils/device/index.ts","../src/utils/async/index.ts","../src/utils/arrays/index.ts"],"sourcesContent":["export function stringToWords(s: string): Array<string> {\n return s.split(\",\").map(s => s.trim().toLowerCase()).filter(_ => _);\n}\n\nexport function sanitizeStr(s: string) {\n return s?.replace(/\\n|\\t/, ' ').replace(/ {2,}/, ' ').trim().toLowerCase() || \"\";\n}\n","export function formatTimeToHHMMSS(timeString: string): string {\n const regex: RegExp = /(?:(\\d+)\\s*h\\s*)?(?:(\\d+)\\s*mi?n?\\s*)?(?:(\\d+)\\s*sec)?/;\n const match: RegExpMatchArray | null = timeString.match(regex);\n const h: number = parseInt(match?.[1] || '0');\n const m: number = parseInt(match?.[2] || '0');\n const s: number = parseInt(match?.[3] || '0');\n const pad = (num: number): string => String(num).padStart(2, '0');\n return `${pad(h)}:${pad(m)}:${pad(s)}`;\n}\n\n// \"01:22:03\" -> 4923\nexport function timeToSeconds(t: string): number {\n const r = /sec|min|h|m/.test(t) ? formatTimeToHHMMSS(t) : t;\n return (r?.match(/\\d+/gm) || [0])\n .reverse()\n .map((s, i) => parseInt(s as string) * 60 ** i)\n .reduce((a, b) => a + b);\n}\n\nexport function parseIntegerOr(n: string | number, or: number): number {\n return (num => Number.isNaN(num) ? or : num)(parseInt(n as string));\n}\n\n// \"data:02;body+head:async;void:;zero:;\"\nexport function parseDataParams(str: string): Record<string, string> {\n return str.split(';').reduce((acc, s) => {\n const parsed = s.match(/([\\+\\w]+):(\\w+)?/);\n if (parsed) {\n const [, key, value] = parsed;\n if (value) {\n key.split('+').forEach(p => { acc[p] = value; });\n }\n }\n return acc;\n }, {} as Record<string, string>);\n}\n\nexport function parseCSSUrl(s: string) {\n return s.replace(/url\\(\"|\\\"\\).*/g, '');\n}\n","export class Observer {\n public observer: IntersectionObserver;\n constructor(private callback: (entry: Element) => void) {\n this.observer = new IntersectionObserver(this.handleIntersection.bind(this));\n }\n\n observe(target: Element) {\n this.observer.observe(target);\n }\n\n throttle(target: Element, throttleTime: number) {\n this.observer.unobserve(target);\n setTimeout(() => this.observer.observe(target), throttleTime);\n }\n\n handleIntersection(entries: Iterable<IntersectionObserverEntry>) {\n for (const entry of entries) {\n if (entry.isIntersecting) {\n this.callback(entry.target);\n }\n }\n }\n\n static observeWhile(target: Element, callback: () => Promise<boolean> | boolean, throttleTime: number) {\n const observer_ = new Observer(async (target: Element) => {\n const condition = await callback();\n if (condition) observer_.throttle(target, throttleTime);\n });\n observer_.observe(target);\n return observer_;\n }\n}\n\nexport class LazyImgLoader {\n public lazyImgObserver: Observer;\n private attributeName = 'data-lazy-load';\n\n constructor(shouldDelazify: (target: Element) => boolean) {\n this.lazyImgObserver = new Observer((target: Element) => {\n if (shouldDelazify(target)) {\n this.delazify(target as HTMLImageElement);\n }\n });\n }\n\n lazify(_target: Element, img: HTMLImageElement, imgSrc: string) {\n if (!img || !imgSrc) return;\n img.setAttribute(this.attributeName, imgSrc);\n img.src = '';\n this.lazyImgObserver.observe(img);\n }\n\n delazify = (target: HTMLImageElement) => {\n this.lazyImgObserver.observer.unobserve(target);\n target.src = target.getAttribute(this.attributeName) as string;\n target.removeAttribute(this.attributeName);\n }\n}\n","export function circularShift(n: number, c = 6, s = 1): number {\n return (n + s) % c || c;\n}\n","export function parseDom(html: string): HTMLElement {\n const parsed = new DOMParser().parseFromString(html, 'text/html').body;\n return parsed.children.length > 1 ? parsed : parsed.firstElementChild as HTMLElement;\n}\n\nexport function copyAttributes(target: HTMLElement | Element, source: HTMLElement | Element) {\n for (const attr of source.attributes) {\n attr.nodeValue && target.setAttribute(attr.nodeName, attr.nodeValue);\n }\n}\n\nexport function replaceElementTag(e: HTMLElement | Element, tagName: string) {\n const newTagElement = document.createElement(tagName);\n copyAttributes(newTagElement, e);\n newTagElement.innerHTML = e.innerHTML;\n e.parentNode?.replaceChild(newTagElement, e);\n return newTagElement;\n}\n\nexport function getAllUniqueParents(elements: HTMLCollection): Array<HTMLElement | Element> {\n return Array.from(elements).reduce((acc, v) => {\n if (v.parentElement && !acc.includes(v.parentElement as HTMLElement)) { acc.push(v.parentElement); }\n return acc;\n }, [] as Array<HTMLElement | Element>);\n}\n\nexport function findNextSibling(el: HTMLElement | Element) {\n if (el.nextElementSibling) return el.nextElementSibling;\n if (el.parentElement) return findNextSibling(el.parentElement);\n return null;\n}\n\nexport function waitForElementExists(parent: HTMLElement | Element, selector: string, callback: (el: Element) => void): void {\n const observer = new MutationObserver((_mutations) => {\n const el = parent.querySelector(selector);\n if (el) {\n observer.disconnect();\n callback(el);\n }\n });\n observer.observe(document.body, { childList: true, subtree: true });\n}\n\nexport function watchElementChildrenCount(element: HTMLElement | Element,\n callback: (observer: MutationObserver, count: number) => void): void {\n let count = element.children.length;\n const observer = new MutationObserver((mutationList, observer) => {\n for (const mutation of mutationList) {\n if (mutation.type === \"childList\") {\n if (count !== element.children.length) {\n count = element.children.length;\n callback(observer, count);\n }\n }\n }\n });\n observer.observe(element, { childList: true });\n}\n\nexport function watchDomChangesWithThrottle(element: HTMLElement | Element, callback: () => void,\n throttle = 1000, options: Record<string, boolean> = { childList: true, subtree: true, attributes: true }) {\n let lastMutationTime: number;\n let timeout: number;\n const observer = new MutationObserver((_mutationList, _observer) => {\n const now = Date.now();\n if (lastMutationTime && now - lastMutationTime < throttle) {\n timeout && clearTimeout(timeout);\n }\n timeout = setTimeout(callback, throttle);\n lastMutationTime = now;\n });\n observer.observe(element, options);\n}\n\nexport function downloader(options = { append: \"\", after: \"\", button: \"\", cbBefore: () => { } }) {\n const btn = parseDom(options.button);\n\n if (options.append) document.querySelector(options.append)?.append(btn);\n if (options.after) document.querySelector(options.after)?.after(btn);\n\n btn.addEventListener('click', (e) => {\n e.preventDefault();\n\n if (options.cbBefore) options.cbBefore();\n\n waitForElementExists(document.body, 'video', (video: Element) => {\n window.location.href = video.getAttribute('src') as string;\n });\n });\n}","import { parseDom } from \"../dom\";\n\nexport const MOBILE_UA = [\n 'Mozilla/5.0 (Linux; Android 10; K)',\n 'AppleWebKit/537.36 (KHTML, like Gecko)',\n 'Chrome/114.0.0.0 Mobile Safari/537.36'].join(' ');\n\nexport function fetchWith(url: string, options: Record<string, boolean> = { html: false, mobile: false }) {\n const reqOpts = {};\n if (options.mobile) Object.assign(reqOpts, { headers: new Headers({ \"User-Agent\": MOBILE_UA }) });\n return fetch(url, reqOpts).then((r) => r.text()).then(r => options.html ? parseDom(r) : r);\n}\n\nexport const fetchHtml = (url: string) => fetchWith(url, { html: true });\n\nexport const fetchText = (url: string) => fetchWith(url);\n\nexport function objectToFormData(object: Record<string, number | boolean | string>): FormData {\n const formData = new FormData();\n Object.entries(object).forEach(([k, v]) => formData.append(k, v as string));\n return formData;\n}\n","export function listenEvents(dom: HTMLElement | Element, events: Array<string>, callback: (e: Event) => void): void {\n for (const e of events) {\n dom.addEventListener(e, callback, true);\n }\n}\n\nexport class Tick {\n private tick?: number;\n private callbackFinal?: () => void;\n\n constructor(private delay: number, private startImmediate: boolean = true) {}\n\n public start(callback: () => void, callbackFinal?: () => void): void {\n this.stop();\n this.callbackFinal = callbackFinal;\n if (this.startImmediate) callback();\n this.tick = window.setInterval(callback, this.delay);\n }\n\n public stop(): void {\n if (this.tick !== undefined) {\n clearInterval(this.tick);\n this.tick = undefined;\n }\n if (this.callbackFinal) {\n this.callbackFinal();\n this.callbackFinal = undefined;\n }\n }\n}\n","export function isMob() {\n return /iPhone|Android/i.test(navigator.userAgent);\n}","// https://2ality.com/2016/10/asynchronous-iteration.html\nexport async function computeAsyncOneAtTime(iterable: Iterable<() => Promise<void>>) {\n const res = [];\n for await (const f of iterable) {\n res.push(await f());\n }\n return res;\n}\n\nexport function wait(milliseconds: number) {\n return new Promise((resolve) => setTimeout(resolve, milliseconds));\n}\n\ninterface AsyncPoolTask {\n v: () => Promise<void>;\n p: number;\n}\n\nexport class AsyncPool {\n private cur = 0;\n private finished: Promise<boolean>;\n private _resolve?: (value: boolean | PromiseLike<boolean>) => void;\n\n public static async doNAsyncAtOnce(max = 1, pool: Array<AsyncPoolTask | (() => Promise<void>)> = []) {\n const spool = new AsyncPool(max);\n pool.forEach(f => spool.push(f));\n return spool.run();\n }\n\n constructor(private max = 1, private pool: Array<AsyncPoolTask> = []) {\n this.finished = new Promise((resolve) => {\n this._resolve = resolve;\n });\n }\n\n private getHighPriorityFirst(p = 0): (() => Promise<void>) | undefined {\n if (p > 3 || this.pool.length === 0) return undefined;\n const i = this.pool.findIndex((e) => e.p === p);\n if (i >= 0) {\n const res = this.pool[i].v;\n this.pool.splice(i, 1);\n return res;\n }\n return this.getHighPriorityFirst(p + 1);\n }\n\n private async runTask() {\n this.cur++;\n const f = this.getHighPriorityFirst();\n await f?.();\n this.cur--;\n this.runTasks();\n }\n\n private runTasks() {\n if (!this.pool.length) {\n this._resolve?.(true);\n return;\n }\n if (this.cur < this.max) {\n this.runTask();\n this.runTasks();\n }\n }\n\n public async run() {\n this.runTasks();\n return this.finished;\n }\n\n public push(x: AsyncPoolTask | (() => Promise<void>)) {\n this.pool.push('p' in x ? x : { v: x, p: 0 });\n }\n}\n\n","export function chunks<T>(arr: Array<T>, n: number): Array<Array<T>> {\n return Array.from({ length: Math.ceil(arr.length / n) }, (_, i) => arr.slice(i * n, i * n + n));\n}\n\nexport function range(size: number, startAt: number = 1, step: number = 1): number[] {\n return Array.from({ length: size }, (_, index) => startAt + index * step);\n}\n"],"names":["s","target","observer"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "billy-herrington-utils",
|
|
3
3
|
"description": "daddy told us not to be ashamed of our utils",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.9",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": ["utils", "observer", "dom", "fetch", "arrays", "typescript"],
|
|
7
7
|
"author": "smartacephale atm.mormon@protonmail.com (https://github.com/smartacephale)",
|
package/src/index.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
export { stringToWords, sanitizeStr } from "./utils/strings";
|
|
2
|
-
export { timeToSeconds, parseCSSUrl, parseDataParams, parseIntegerOr } from "./utils/parsers";
|
|
3
|
-
export { Observer, LazyImgLoader } from "./utils/observers";
|
|
4
|
-
export { circularShift } from "./utils/math";
|
|
5
|
-
export { MOBILE_UA, fetchHtml, fetchText, fetchWith, objectToFormData } from "./utils/fetch";
|
|
6
|
-
export { Tick, listenEvents } from "./utils/events";
|
|
7
|
-
export {
|
|
8
|
-
parseDom,
|
|
9
|
-
copyAttributes,
|
|
10
|
-
downloader,
|
|
11
|
-
findNextSibling,
|
|
12
|
-
getAllUniqueParents,
|
|
13
|
-
replaceElementTag,
|
|
14
|
-
waitForElementExists,
|
|
15
|
-
watchDomChangesWithThrottle,
|
|
16
|
-
watchElementChildrenCount
|
|
17
|
-
} from "./utils/dom";
|
|
18
|
-
export { isMob } from "./utils/device";
|
|
19
|
-
export { computeAsyncOneAtTime, AsyncPool, wait } from "./utils/async";
|
|
1
|
+
export { stringToWords, sanitizeStr } from "./utils/strings";
|
|
2
|
+
export { timeToSeconds, parseCSSUrl, parseDataParams, parseIntegerOr } from "./utils/parsers";
|
|
3
|
+
export { Observer, LazyImgLoader } from "./utils/observers";
|
|
4
|
+
export { circularShift } from "./utils/math";
|
|
5
|
+
export { MOBILE_UA, fetchHtml, fetchText, fetchWith, objectToFormData } from "./utils/fetch";
|
|
6
|
+
export { Tick, listenEvents } from "./utils/events";
|
|
7
|
+
export {
|
|
8
|
+
parseDom,
|
|
9
|
+
copyAttributes,
|
|
10
|
+
downloader,
|
|
11
|
+
findNextSibling,
|
|
12
|
+
getAllUniqueParents,
|
|
13
|
+
replaceElementTag,
|
|
14
|
+
waitForElementExists,
|
|
15
|
+
watchDomChangesWithThrottle,
|
|
16
|
+
watchElementChildrenCount
|
|
17
|
+
} from "./utils/dom";
|
|
18
|
+
export { isMob } from "./utils/device";
|
|
19
|
+
export { computeAsyncOneAtTime, AsyncPool, wait } from "./utils/async";
|
|
20
20
|
export { chunks, range } from "./utils/arrays";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export function chunks<T>(arr: Array<T>, n: number): Array<Array<T>> {
|
|
2
|
-
return Array.from({ length: Math.ceil(arr.length / n) }, (_, i) => arr.slice(i * n, i * n + n));
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export function range(size: number, startAt: number = 1, step: number = 1): number[] {
|
|
6
|
-
return Array.from({ length: size }, (_, index) => startAt + index * step);
|
|
7
|
-
}
|
|
1
|
+
export function chunks<T>(arr: Array<T>, n: number): Array<Array<T>> {
|
|
2
|
+
return Array.from({ length: Math.ceil(arr.length / n) }, (_, i) => arr.slice(i * n, i * n + n));
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function range(size: number, startAt: number = 1, step: number = 1): number[] {
|
|
6
|
+
return Array.from({ length: size }, (_, index) => startAt + index * step);
|
|
7
|
+
}
|
package/src/utils/async/index.ts
CHANGED
|
@@ -1,75 +1,75 @@
|
|
|
1
|
-
// https://2ality.com/2016/10/asynchronous-iteration.html
|
|
2
|
-
export async function computeAsyncOneAtTime(iterable: Iterable<() => Promise<void>>) {
|
|
3
|
-
const res = [];
|
|
4
|
-
for await (const f of iterable) {
|
|
5
|
-
res.push(await f());
|
|
6
|
-
}
|
|
7
|
-
return res;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function wait(milliseconds: number) {
|
|
11
|
-
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
interface AsyncPoolTask {
|
|
15
|
-
v: () => Promise<void>;
|
|
16
|
-
p: number;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export class AsyncPool {
|
|
20
|
-
private cur = 0;
|
|
21
|
-
private finished: Promise<boolean>;
|
|
22
|
-
private _resolve?: (value: boolean | PromiseLike<boolean>) => void;
|
|
23
|
-
|
|
24
|
-
public static async doNAsyncAtOnce(max = 1, pool: Array<AsyncPoolTask | (() => Promise<void>)> = []) {
|
|
25
|
-
const spool = new AsyncPool(max);
|
|
26
|
-
pool.forEach(f => spool.push(f));
|
|
27
|
-
return spool.run();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
constructor(private max = 1, private pool: Array<AsyncPoolTask> = []) {
|
|
31
|
-
this.finished = new Promise((resolve) => {
|
|
32
|
-
this._resolve = resolve;
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
private getHighPriorityFirst(p = 0): (() => Promise<void>) | undefined {
|
|
37
|
-
if (p > 3 || this.pool.length === 0) return undefined;
|
|
38
|
-
const i = this.pool.findIndex((e) => e.p === p);
|
|
39
|
-
if (i >= 0) {
|
|
40
|
-
const res = this.pool[i].v;
|
|
41
|
-
this.pool.splice(i, 1);
|
|
42
|
-
return res;
|
|
43
|
-
}
|
|
44
|
-
return this.getHighPriorityFirst(p + 1);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
private async runTask() {
|
|
48
|
-
this.cur++;
|
|
49
|
-
const f = this.getHighPriorityFirst();
|
|
50
|
-
await f?.();
|
|
51
|
-
this.cur--;
|
|
52
|
-
this.runTasks();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
private runTasks() {
|
|
56
|
-
if (!this.pool.length) {
|
|
57
|
-
this._resolve?.(true);
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
if (this.cur < this.max) {
|
|
61
|
-
this.runTask();
|
|
62
|
-
this.runTasks();
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
public async run() {
|
|
67
|
-
this.runTasks();
|
|
68
|
-
return this.finished;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
public push(x: AsyncPoolTask | (() => Promise<void>)) {
|
|
72
|
-
this.pool.push('p' in x ? x : { v: x, p: 0 });
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
1
|
+
// https://2ality.com/2016/10/asynchronous-iteration.html
|
|
2
|
+
export async function computeAsyncOneAtTime(iterable: Iterable<() => Promise<void>>) {
|
|
3
|
+
const res = [];
|
|
4
|
+
for await (const f of iterable) {
|
|
5
|
+
res.push(await f());
|
|
6
|
+
}
|
|
7
|
+
return res;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function wait(milliseconds: number) {
|
|
11
|
+
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface AsyncPoolTask {
|
|
15
|
+
v: () => Promise<void>;
|
|
16
|
+
p: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class AsyncPool {
|
|
20
|
+
private cur = 0;
|
|
21
|
+
private finished: Promise<boolean>;
|
|
22
|
+
private _resolve?: (value: boolean | PromiseLike<boolean>) => void;
|
|
23
|
+
|
|
24
|
+
public static async doNAsyncAtOnce(max = 1, pool: Array<AsyncPoolTask | (() => Promise<void>)> = []) {
|
|
25
|
+
const spool = new AsyncPool(max);
|
|
26
|
+
pool.forEach(f => spool.push(f));
|
|
27
|
+
return spool.run();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
constructor(private max = 1, private pool: Array<AsyncPoolTask> = []) {
|
|
31
|
+
this.finished = new Promise((resolve) => {
|
|
32
|
+
this._resolve = resolve;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private getHighPriorityFirst(p = 0): (() => Promise<void>) | undefined {
|
|
37
|
+
if (p > 3 || this.pool.length === 0) return undefined;
|
|
38
|
+
const i = this.pool.findIndex((e) => e.p === p);
|
|
39
|
+
if (i >= 0) {
|
|
40
|
+
const res = this.pool[i].v;
|
|
41
|
+
this.pool.splice(i, 1);
|
|
42
|
+
return res;
|
|
43
|
+
}
|
|
44
|
+
return this.getHighPriorityFirst(p + 1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private async runTask() {
|
|
48
|
+
this.cur++;
|
|
49
|
+
const f = this.getHighPriorityFirst();
|
|
50
|
+
await f?.();
|
|
51
|
+
this.cur--;
|
|
52
|
+
this.runTasks();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private runTasks() {
|
|
56
|
+
if (!this.pool.length) {
|
|
57
|
+
this._resolve?.(true);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (this.cur < this.max) {
|
|
61
|
+
this.runTask();
|
|
62
|
+
this.runTasks();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public async run() {
|
|
67
|
+
this.runTasks();
|
|
68
|
+
return this.finished;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public push(x: AsyncPoolTask | (() => Promise<void>)) {
|
|
72
|
+
this.pool.push('p' in x ? x : { v: x, p: 0 });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export function isMob() {
|
|
2
|
-
return /iPhone|Android/i.test(navigator.userAgent);
|
|
1
|
+
export function isMob() {
|
|
2
|
+
return /iPhone|Android/i.test(navigator.userAgent);
|
|
3
3
|
}
|
package/src/utils/dom/index.ts
CHANGED
|
@@ -1,90 +1,90 @@
|
|
|
1
|
-
export function parseDom(html: string): HTMLElement {
|
|
2
|
-
const parsed = new DOMParser().parseFromString(html, 'text/html').body;
|
|
3
|
-
return parsed.children.length > 1 ? parsed : parsed.firstElementChild as HTMLElement;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export function copyAttributes(target: HTMLElement | Element, source: HTMLElement | Element) {
|
|
7
|
-
for (const attr of source.attributes) {
|
|
8
|
-
attr.nodeValue && target.setAttribute(attr.nodeName, attr.nodeValue);
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function replaceElementTag(e: HTMLElement | Element, tagName: string) {
|
|
13
|
-
const newTagElement = document.createElement(tagName);
|
|
14
|
-
copyAttributes(newTagElement, e);
|
|
15
|
-
newTagElement.innerHTML = e.innerHTML;
|
|
16
|
-
e.parentNode?.replaceChild(newTagElement, e);
|
|
17
|
-
return newTagElement;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function getAllUniqueParents(elements: HTMLCollection): Array<HTMLElement | Element> {
|
|
21
|
-
return Array.from(elements).reduce((acc, v) => {
|
|
22
|
-
if (v.parentElement && !acc.includes(v.parentElement as HTMLElement)) { acc.push(v.parentElement); }
|
|
23
|
-
return acc;
|
|
24
|
-
}, [] as Array<HTMLElement | Element>);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function findNextSibling(el: HTMLElement | Element) {
|
|
28
|
-
if (el.nextElementSibling) return el.nextElementSibling;
|
|
29
|
-
if (el.parentElement) return findNextSibling(el.parentElement);
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function waitForElementExists(parent: HTMLElement | Element, selector: string, callback: (el: Element) => void): void {
|
|
34
|
-
const observer = new MutationObserver((_mutations) => {
|
|
35
|
-
const el = parent.querySelector(selector);
|
|
36
|
-
if (el) {
|
|
37
|
-
observer.disconnect();
|
|
38
|
-
callback(el);
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
observer.observe(document.body, { childList: true, subtree: true });
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function watchElementChildrenCount(element: HTMLElement | Element,
|
|
45
|
-
callback: (observer: MutationObserver, count: number) => void): void {
|
|
46
|
-
let count = element.children.length;
|
|
47
|
-
const observer = new MutationObserver((mutationList, observer) => {
|
|
48
|
-
for (const mutation of mutationList) {
|
|
49
|
-
if (mutation.type === "childList") {
|
|
50
|
-
if (count !== element.children.length) {
|
|
51
|
-
count = element.children.length;
|
|
52
|
-
callback(observer, count);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
observer.observe(element, { childList: true });
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function watchDomChangesWithThrottle(element: HTMLElement | Element, callback: () => void,
|
|
61
|
-
throttle = 1000, options: Record<string, boolean> = { childList: true, subtree: true, attributes: true }) {
|
|
62
|
-
let lastMutationTime: number;
|
|
63
|
-
let timeout: number;
|
|
64
|
-
const observer = new MutationObserver((_mutationList, _observer) => {
|
|
65
|
-
const now = Date.now();
|
|
66
|
-
if (lastMutationTime && now - lastMutationTime < throttle) {
|
|
67
|
-
timeout && clearTimeout(timeout);
|
|
68
|
-
}
|
|
69
|
-
timeout = setTimeout(callback, throttle);
|
|
70
|
-
lastMutationTime = now;
|
|
71
|
-
});
|
|
72
|
-
observer.observe(element, options);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function downloader(options = { append: "", after: "", button: "", cbBefore: () => { } }) {
|
|
76
|
-
const btn = parseDom(options.button);
|
|
77
|
-
|
|
78
|
-
if (options.append) document.querySelector(options.append)?.append(btn);
|
|
79
|
-
if (options.after) document.querySelector(options.after)?.after(btn);
|
|
80
|
-
|
|
81
|
-
btn.addEventListener('click', (e) => {
|
|
82
|
-
e.preventDefault();
|
|
83
|
-
|
|
84
|
-
if (options.cbBefore) options.cbBefore();
|
|
85
|
-
|
|
86
|
-
waitForElementExists(document.body, 'video', (video: Element) => {
|
|
87
|
-
window.location.href = video.getAttribute('src') as string;
|
|
88
|
-
});
|
|
89
|
-
});
|
|
1
|
+
export function parseDom(html: string): HTMLElement {
|
|
2
|
+
const parsed = new DOMParser().parseFromString(html, 'text/html').body;
|
|
3
|
+
return parsed.children.length > 1 ? parsed : parsed.firstElementChild as HTMLElement;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function copyAttributes(target: HTMLElement | Element, source: HTMLElement | Element) {
|
|
7
|
+
for (const attr of source.attributes) {
|
|
8
|
+
attr.nodeValue && target.setAttribute(attr.nodeName, attr.nodeValue);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function replaceElementTag(e: HTMLElement | Element, tagName: string) {
|
|
13
|
+
const newTagElement = document.createElement(tagName);
|
|
14
|
+
copyAttributes(newTagElement, e);
|
|
15
|
+
newTagElement.innerHTML = e.innerHTML;
|
|
16
|
+
e.parentNode?.replaceChild(newTagElement, e);
|
|
17
|
+
return newTagElement;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function getAllUniqueParents(elements: HTMLCollection): Array<HTMLElement | Element> {
|
|
21
|
+
return Array.from(elements).reduce((acc, v) => {
|
|
22
|
+
if (v.parentElement && !acc.includes(v.parentElement as HTMLElement)) { acc.push(v.parentElement); }
|
|
23
|
+
return acc;
|
|
24
|
+
}, [] as Array<HTMLElement | Element>);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function findNextSibling(el: HTMLElement | Element) {
|
|
28
|
+
if (el.nextElementSibling) return el.nextElementSibling;
|
|
29
|
+
if (el.parentElement) return findNextSibling(el.parentElement);
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function waitForElementExists(parent: HTMLElement | Element, selector: string, callback: (el: Element) => void): void {
|
|
34
|
+
const observer = new MutationObserver((_mutations) => {
|
|
35
|
+
const el = parent.querySelector(selector);
|
|
36
|
+
if (el) {
|
|
37
|
+
observer.disconnect();
|
|
38
|
+
callback(el);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function watchElementChildrenCount(element: HTMLElement | Element,
|
|
45
|
+
callback: (observer: MutationObserver, count: number) => void): void {
|
|
46
|
+
let count = element.children.length;
|
|
47
|
+
const observer = new MutationObserver((mutationList, observer) => {
|
|
48
|
+
for (const mutation of mutationList) {
|
|
49
|
+
if (mutation.type === "childList") {
|
|
50
|
+
if (count !== element.children.length) {
|
|
51
|
+
count = element.children.length;
|
|
52
|
+
callback(observer, count);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
observer.observe(element, { childList: true });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function watchDomChangesWithThrottle(element: HTMLElement | Element, callback: () => void,
|
|
61
|
+
throttle = 1000, options: Record<string, boolean> = { childList: true, subtree: true, attributes: true }) {
|
|
62
|
+
let lastMutationTime: number;
|
|
63
|
+
let timeout: number;
|
|
64
|
+
const observer = new MutationObserver((_mutationList, _observer) => {
|
|
65
|
+
const now = Date.now();
|
|
66
|
+
if (lastMutationTime && now - lastMutationTime < throttle) {
|
|
67
|
+
timeout && clearTimeout(timeout);
|
|
68
|
+
}
|
|
69
|
+
timeout = setTimeout(callback, throttle);
|
|
70
|
+
lastMutationTime = now;
|
|
71
|
+
});
|
|
72
|
+
observer.observe(element, options);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function downloader(options = { append: "", after: "", button: "", cbBefore: () => { } }) {
|
|
76
|
+
const btn = parseDom(options.button);
|
|
77
|
+
|
|
78
|
+
if (options.append) document.querySelector(options.append)?.append(btn);
|
|
79
|
+
if (options.after) document.querySelector(options.after)?.after(btn);
|
|
80
|
+
|
|
81
|
+
btn.addEventListener('click', (e) => {
|
|
82
|
+
e.preventDefault();
|
|
83
|
+
|
|
84
|
+
if (options.cbBefore) options.cbBefore();
|
|
85
|
+
|
|
86
|
+
waitForElementExists(document.body, 'video', (video: Element) => {
|
|
87
|
+
window.location.href = video.getAttribute('src') as string;
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
90
|
}
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
export function listenEvents(dom: HTMLElement | Element, events: Array<string>, callback: (e: Event) => void): void {
|
|
2
|
-
for (const e of events) {
|
|
3
|
-
dom.addEventListener(e, callback, true);
|
|
4
|
-
}
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export class Tick {
|
|
8
|
-
private tick?: number;
|
|
9
|
-
private callbackFinal?: () => void;
|
|
10
|
-
|
|
11
|
-
constructor(private delay: number, private startImmediate: boolean = true) {}
|
|
12
|
-
|
|
13
|
-
public start(callback: () => void, callbackFinal?: () => void): void {
|
|
14
|
-
this.stop();
|
|
15
|
-
this.callbackFinal = callbackFinal;
|
|
16
|
-
if (this.startImmediate) callback();
|
|
17
|
-
this.tick = window.setInterval(callback, this.delay);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
public stop(): void {
|
|
21
|
-
if (this.tick !== undefined) {
|
|
22
|
-
clearInterval(this.tick);
|
|
23
|
-
this.tick = undefined;
|
|
24
|
-
}
|
|
25
|
-
if (this.callbackFinal) {
|
|
26
|
-
this.callbackFinal();
|
|
27
|
-
this.callbackFinal = undefined;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
1
|
+
export function listenEvents(dom: HTMLElement | Element, events: Array<string>, callback: (e: Event) => void): void {
|
|
2
|
+
for (const e of events) {
|
|
3
|
+
dom.addEventListener(e, callback, true);
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export class Tick {
|
|
8
|
+
private tick?: number;
|
|
9
|
+
private callbackFinal?: () => void;
|
|
10
|
+
|
|
11
|
+
constructor(private delay: number, private startImmediate: boolean = true) {}
|
|
12
|
+
|
|
13
|
+
public start(callback: () => void, callbackFinal?: () => void): void {
|
|
14
|
+
this.stop();
|
|
15
|
+
this.callbackFinal = callbackFinal;
|
|
16
|
+
if (this.startImmediate) callback();
|
|
17
|
+
this.tick = window.setInterval(callback, this.delay);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public stop(): void {
|
|
21
|
+
if (this.tick !== undefined) {
|
|
22
|
+
clearInterval(this.tick);
|
|
23
|
+
this.tick = undefined;
|
|
24
|
+
}
|
|
25
|
+
if (this.callbackFinal) {
|
|
26
|
+
this.callbackFinal();
|
|
27
|
+
this.callbackFinal = undefined;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
package/src/utils/fetch/index.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import { parseDom } from "../dom";
|
|
2
|
-
|
|
3
|
-
export const MOBILE_UA = [
|
|
4
|
-
'Mozilla/5.0 (Linux; Android 10; K)',
|
|
5
|
-
'AppleWebKit/537.36 (KHTML, like Gecko)',
|
|
6
|
-
'Chrome/114.0.0.0 Mobile Safari/537.36'].join(' ');
|
|
7
|
-
|
|
8
|
-
export function fetchWith(url: string, options: Record<string, boolean> = { html: false, mobile: false }) {
|
|
9
|
-
const reqOpts = {};
|
|
10
|
-
if (options.mobile) Object.assign(reqOpts, { headers: new Headers({ "User-Agent": MOBILE_UA }) });
|
|
11
|
-
return fetch(url, reqOpts).then((r) => r.text()).then(r => options.html ? parseDom(r) : r);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const fetchHtml = (url: string) => fetchWith(url, { html: true });
|
|
15
|
-
|
|
16
|
-
export const fetchText = (url: string) => fetchWith(url);
|
|
17
|
-
|
|
18
|
-
export function objectToFormData(object: Record<string, number | boolean | string>): FormData {
|
|
19
|
-
const formData = new FormData();
|
|
20
|
-
Object.entries(object).forEach(([k, v]) => formData.append(k, v as string));
|
|
21
|
-
return formData;
|
|
22
|
-
}
|
|
1
|
+
import { parseDom } from "../dom";
|
|
2
|
+
|
|
3
|
+
export const MOBILE_UA = [
|
|
4
|
+
'Mozilla/5.0 (Linux; Android 10; K)',
|
|
5
|
+
'AppleWebKit/537.36 (KHTML, like Gecko)',
|
|
6
|
+
'Chrome/114.0.0.0 Mobile Safari/537.36'].join(' ');
|
|
7
|
+
|
|
8
|
+
export function fetchWith(url: string, options: Record<string, boolean> = { html: false, mobile: false }) {
|
|
9
|
+
const reqOpts = {};
|
|
10
|
+
if (options.mobile) Object.assign(reqOpts, { headers: new Headers({ "User-Agent": MOBILE_UA }) });
|
|
11
|
+
return fetch(url, reqOpts).then((r) => r.text()).then(r => options.html ? parseDom(r) : r);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const fetchHtml = (url: string) => fetchWith(url, { html: true });
|
|
15
|
+
|
|
16
|
+
export const fetchText = (url: string) => fetchWith(url);
|
|
17
|
+
|
|
18
|
+
export function objectToFormData(object: Record<string, number | boolean | string>): FormData {
|
|
19
|
+
const formData = new FormData();
|
|
20
|
+
Object.entries(object).forEach(([k, v]) => formData.append(k, v as string));
|
|
21
|
+
return formData;
|
|
22
|
+
}
|
package/src/utils/math/index.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export function circularShift(n: number, c = 6, s = 1): number {
|
|
2
|
-
return (n + s) % c || c;
|
|
3
|
-
}
|
|
1
|
+
export function circularShift(n: number, c = 6, s = 1): number {
|
|
2
|
+
return (n + s) % c || c;
|
|
3
|
+
}
|
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
export class Observer {
|
|
2
|
-
public observer: IntersectionObserver;
|
|
3
|
-
constructor(private callback: (entry: Element) => void) {
|
|
4
|
-
this.observer = new IntersectionObserver(this.handleIntersection.bind(this));
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
observe(target: Element) {
|
|
8
|
-
this.observer.observe(target);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
throttle(target: Element, throttleTime: number) {
|
|
12
|
-
this.observer.unobserve(target);
|
|
13
|
-
setTimeout(() => this.observer.observe(target), throttleTime);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
handleIntersection(entries: Iterable<IntersectionObserverEntry>) {
|
|
17
|
-
for (const entry of entries) {
|
|
18
|
-
if (entry.isIntersecting) {
|
|
19
|
-
this.callback(entry.target);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
static observeWhile(target: Element, callback: () => Promise<boolean> | boolean, throttleTime: number) {
|
|
25
|
-
const observer_ = new Observer(async (target: Element) => {
|
|
26
|
-
const condition = await callback();
|
|
27
|
-
if (condition) observer_.throttle(target, throttleTime);
|
|
28
|
-
});
|
|
29
|
-
observer_.observe(target);
|
|
30
|
-
return observer_;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export class LazyImgLoader {
|
|
35
|
-
public lazyImgObserver: Observer;
|
|
36
|
-
private attributeName = 'data-lazy-load';
|
|
37
|
-
|
|
38
|
-
constructor(shouldDelazify: (target: Element) => boolean) {
|
|
39
|
-
this.lazyImgObserver = new Observer((target: Element) => {
|
|
40
|
-
if (shouldDelazify(target)) {
|
|
41
|
-
this.delazify(target as HTMLImageElement);
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
lazify(_target: Element, img: HTMLImageElement, imgSrc: string) {
|
|
47
|
-
if (!img || !imgSrc) return;
|
|
48
|
-
img.setAttribute(this.attributeName, imgSrc);
|
|
49
|
-
img.src = '';
|
|
50
|
-
this.lazyImgObserver.observe(img);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
delazify = (target: HTMLImageElement) => {
|
|
54
|
-
this.lazyImgObserver.observer.unobserve(target);
|
|
55
|
-
target.src = target.getAttribute(this.attributeName) as string;
|
|
56
|
-
target.removeAttribute(this.attributeName);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
1
|
+
export class Observer {
|
|
2
|
+
public observer: IntersectionObserver;
|
|
3
|
+
constructor(private callback: (entry: Element) => void) {
|
|
4
|
+
this.observer = new IntersectionObserver(this.handleIntersection.bind(this));
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
observe(target: Element) {
|
|
8
|
+
this.observer.observe(target);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
throttle(target: Element, throttleTime: number) {
|
|
12
|
+
this.observer.unobserve(target);
|
|
13
|
+
setTimeout(() => this.observer.observe(target), throttleTime);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
handleIntersection(entries: Iterable<IntersectionObserverEntry>) {
|
|
17
|
+
for (const entry of entries) {
|
|
18
|
+
if (entry.isIntersecting) {
|
|
19
|
+
this.callback(entry.target);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static observeWhile(target: Element, callback: () => Promise<boolean> | boolean, throttleTime: number) {
|
|
25
|
+
const observer_ = new Observer(async (target: Element) => {
|
|
26
|
+
const condition = await callback();
|
|
27
|
+
if (condition) observer_.throttle(target, throttleTime);
|
|
28
|
+
});
|
|
29
|
+
observer_.observe(target);
|
|
30
|
+
return observer_;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class LazyImgLoader {
|
|
35
|
+
public lazyImgObserver: Observer;
|
|
36
|
+
private attributeName = 'data-lazy-load';
|
|
37
|
+
|
|
38
|
+
constructor(shouldDelazify: (target: Element) => boolean) {
|
|
39
|
+
this.lazyImgObserver = new Observer((target: Element) => {
|
|
40
|
+
if (shouldDelazify(target)) {
|
|
41
|
+
this.delazify(target as HTMLImageElement);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
lazify(_target: Element, img: HTMLImageElement, imgSrc: string) {
|
|
47
|
+
if (!img || !imgSrc) return;
|
|
48
|
+
img.setAttribute(this.attributeName, imgSrc);
|
|
49
|
+
img.src = '';
|
|
50
|
+
this.lazyImgObserver.observe(img);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
delazify = (target: HTMLImageElement) => {
|
|
54
|
+
this.lazyImgObserver.observer.unobserve(target);
|
|
55
|
+
target.src = target.getAttribute(this.attributeName) as string;
|
|
56
|
+
target.removeAttribute(this.attributeName);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -1,28 +1,40 @@
|
|
|
1
|
-
export function
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
1
|
+
export function formatTimeToHHMMSS(timeString: string): string {
|
|
2
|
+
const regex: RegExp = /(?:(\d+)\s*h\s*)?(?:(\d+)\s*mi?n?\s*)?(?:(\d+)\s*sec)?/;
|
|
3
|
+
const match: RegExpMatchArray | null = timeString.match(regex);
|
|
4
|
+
const h: number = parseInt(match?.[1] || '0');
|
|
5
|
+
const m: number = parseInt(match?.[2] || '0');
|
|
6
|
+
const s: number = parseInt(match?.[3] || '0');
|
|
7
|
+
const pad = (num: number): string => String(num).padStart(2, '0');
|
|
8
|
+
return `${pad(h)}:${pad(m)}:${pad(s)}`;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// "01:22:03" -> 4923
|
|
12
|
+
export function timeToSeconds(t: string): number {
|
|
13
|
+
const r = /sec|min|h|m/.test(t) ? formatTimeToHHMMSS(t) : t;
|
|
14
|
+
return (r?.match(/\d+/gm) || [0])
|
|
15
|
+
.reverse()
|
|
16
|
+
.map((s, i) => parseInt(s as string) * 60 ** i)
|
|
17
|
+
.reduce((a, b) => a + b);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function parseIntegerOr(n: string | number, or: number): number {
|
|
21
|
+
return (num => Number.isNaN(num) ? or : num)(parseInt(n as string));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// "data:02;body+head:async;void:;zero:;"
|
|
25
|
+
export function parseDataParams(str: string): Record<string, string> {
|
|
26
|
+
return str.split(';').reduce((acc, s) => {
|
|
27
|
+
const parsed = s.match(/([\+\w]+):(\w+)?/);
|
|
28
|
+
if (parsed) {
|
|
29
|
+
const [, key, value] = parsed;
|
|
30
|
+
if (value) {
|
|
31
|
+
key.split('+').forEach(p => { acc[p] = value; });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return acc;
|
|
35
|
+
}, {} as Record<string, string>);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function parseCSSUrl(s: string) {
|
|
39
|
+
return s.replace(/url\("|\"\).*/g, '');
|
|
40
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export function stringToWords(s: string): Array<string> {
|
|
2
|
-
return s.split(",").map(s => s.trim().toLowerCase()).filter(_ => _);
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export function sanitizeStr(s: string) {
|
|
6
|
-
return s?.replace(/\n|\t/, ' ').replace(/ {2,}/, ' ').trim().toLowerCase() || "";
|
|
7
|
-
}
|
|
1
|
+
export function stringToWords(s: string): Array<string> {
|
|
2
|
+
return s.split(",").map(s => s.trim().toLowerCase()).filter(_ => _);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function sanitizeStr(s: string) {
|
|
6
|
+
return s?.replace(/\n|\t/, ' ').replace(/ {2,}/, ' ').trim().toLowerCase() || "";
|
|
7
|
+
}
|