billy-herrington-utils 1.3.5 → 1.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/billy-herrington-utils.es.js +32 -3
- package/dist/billy-herrington-utils.es.js.map +1 -1
- package/dist/billy-herrington-utils.umd.js +32 -3
- package/dist/billy-herrington-utils.umd.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/package.json +1 -1
- package/src/data-manager/index.ts +35 -3
- package/src/utils/jabroni-outfit-wrap/index.ts +0 -3
|
@@ -180,6 +180,11 @@ function downloader(options = { append: "", after: "", button: "", cbBefore: ()
|
|
|
180
180
|
});
|
|
181
181
|
});
|
|
182
182
|
}
|
|
183
|
+
function exterminateVideo(video) {
|
|
184
|
+
video.removeAttribute("src");
|
|
185
|
+
video.load();
|
|
186
|
+
video.remove();
|
|
187
|
+
}
|
|
183
188
|
const MOBILE_UA = [
|
|
184
189
|
"Mozilla/5.0 (Linux; Android 10; K)",
|
|
185
190
|
"AppleWebKit/537.36 (KHTML, like Gecko)",
|
|
@@ -319,6 +324,15 @@ class DataFilter {
|
|
|
319
324
|
};
|
|
320
325
|
};
|
|
321
326
|
});
|
|
327
|
+
__publicField(this, "filterHD", () => {
|
|
328
|
+
return (v) => {
|
|
329
|
+
const isHD = this.rules.IS_HD(v.element);
|
|
330
|
+
return {
|
|
331
|
+
tag: "filter-hd",
|
|
332
|
+
condition: this.state.filterHD && isHD
|
|
333
|
+
};
|
|
334
|
+
};
|
|
335
|
+
});
|
|
322
336
|
__publicField(this, "filterDuration", () => {
|
|
323
337
|
return (v) => {
|
|
324
338
|
const notInRange = v.duration < this.state.filterDurationFrom || v.duration > this.state.filterDurationTo;
|
|
@@ -393,7 +407,7 @@ class DataManager {
|
|
|
393
407
|
);
|
|
394
408
|
this.applyFilters(filters, offset);
|
|
395
409
|
});
|
|
396
|
-
__publicField(this, "
|
|
410
|
+
__publicField(this, "parseData", (html, container, removeDuplicates = false, shouldLazify = true) => {
|
|
397
411
|
const thumbs = this.rules.GET_THUMBS(html);
|
|
398
412
|
const data_offset = this.data.size;
|
|
399
413
|
for (const thumbElement of thumbs) {
|
|
@@ -402,8 +416,8 @@ class DataManager {
|
|
|
402
416
|
if (removeDuplicates) thumbElement.remove();
|
|
403
417
|
continue;
|
|
404
418
|
}
|
|
405
|
-
const
|
|
406
|
-
this.data.set(url, { element: thumbElement,
|
|
419
|
+
const data = this.rules.THUMB_DATA(thumbElement);
|
|
420
|
+
this.data.set(url, { element: thumbElement, ...data });
|
|
407
421
|
if (shouldLazify) {
|
|
408
422
|
const { img, imgSrc } = this.rules.THUMB_IMG_DATA(thumbElement);
|
|
409
423
|
this.lazyImgLoader.lazify(thumbElement, img, imgSrc);
|
|
@@ -420,6 +434,10 @@ class DataManager {
|
|
|
420
434
|
(target) => !this.isFiltered(target)
|
|
421
435
|
);
|
|
422
436
|
this.dataFilters = new DataFilter(rules, state).filters;
|
|
437
|
+
Object.assign(unsafeWindow || window, {
|
|
438
|
+
sortByViews: this.sort("views"),
|
|
439
|
+
sortByDuration: this.sort("duration")
|
|
440
|
+
});
|
|
423
441
|
}
|
|
424
442
|
static filterDSLToRegex(str) {
|
|
425
443
|
const toFullWord = (w) => `(^|\\ )${w}($|\\ )`;
|
|
@@ -429,6 +447,16 @@ class DataManager {
|
|
|
429
447
|
isFiltered(el) {
|
|
430
448
|
return el.className.includes("filtered");
|
|
431
449
|
}
|
|
450
|
+
sort(propName) {
|
|
451
|
+
const sorted = Array.from(this.data.keys()).sort((b, a) => {
|
|
452
|
+
return this.data.get(a)[propName] - this.data.get(b)[propName];
|
|
453
|
+
});
|
|
454
|
+
const container = this.data.get(sorted[0]).element.parentElement;
|
|
455
|
+
sorted.forEach((s) => {
|
|
456
|
+
const e = this.data.get(s).element;
|
|
457
|
+
container.append(e);
|
|
458
|
+
});
|
|
459
|
+
}
|
|
432
460
|
}
|
|
433
461
|
class InfiniteScroller {
|
|
434
462
|
constructor({
|
|
@@ -642,6 +670,7 @@ export {
|
|
|
642
670
|
copyAttributes,
|
|
643
671
|
createInfiniteScroller,
|
|
644
672
|
downloader,
|
|
673
|
+
exterminateVideo,
|
|
645
674
|
fetchHtml,
|
|
646
675
|
fetchText,
|
|
647
676
|
fetchWith,
|
|
@@ -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","../src/data-manager/index.ts","../src/utils/infinite-scroll/index.ts","../src/utils/jabroni-outfit-wrap/index.ts","../src/utils/userscript-utils/rules.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(\n target: Element,\n callback: () => Promise<boolean> | boolean,\n throttleTime: number,\n ) {\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(\n element: HTMLElement | Element, \n callback: () => void,\n throttle = 1000,\n times = Infinity,\n options: Record<string, boolean> = { childList: true, subtree: true, attributes: true }\n) {\n let lastMutationTime: number;\n let timeout: number;\n let times_ = times;\n const observer = new MutationObserver((_mutationList, _observer) => {\n if (times_ !== Infinity && times_ < 1) {\n observer.disconnect();\n return;\n }\n times_--;\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 return observer;\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',\n].join(' ');\n\nexport function fetchWith(\n url: string,\n options: Record<string, boolean> = { html: false, mobile: false },\n) {\n const reqOpts = {};\n if (options.mobile) Object.assign(reqOpts, { headers: new Headers({ 'User-Agent': MOBILE_UA }) });\n return fetch(url, reqOpts)\n .then((r) => r.text())\n .then((r) => (options.html ? parseDom(r) : r));\n}\n\nexport const fetchHtml = (url: string) => fetchWith(url, { html: true }) as Promise<HTMLElement>;\n\nexport const fetchText = (url: string) => fetchWith(url) as Promise<string>;\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","import { LazyImgLoader } from '../utils/observers';\nimport { stringToWords } from '../utils/strings';\n\ninterface DataFilterState {\n filterPublic: boolean;\n filterPrivate: boolean;\n filterDuration: boolean;\n filterDurationFrom: number;\n filterDurationTo: number;\n filterExclude: boolean;\n filterExcludeWords: string;\n filterInclude: boolean;\n filterIncludeWords: string;\n}\n\ninterface FilterResult {\n tag: string;\n condition: boolean;\n}\n\ntype FilterInput = Record<string, string | number | boolean | HTMLElement>;\ntype FilterFunction = (v: FilterInput) => FilterResult;\n\nclass DataFilter {\n private state: DataFilterState;\n private rules: IRules;\n public filters: { [key: string]: () => FilterFunction };\n\n constructor(rules: IRules, state: DataFilterState) {\n this.state = state;\n this.rules = rules;\n\n const methods = Object.getOwnPropertyNames(this);\n this.filters = methods.reduce((acc: { [key: string]: () => FilterFunction }, k) => {\n if (k in this.state) {\n acc[k] = this[k as keyof DataFilter] as unknown as () => FilterFunction;\n //@ts-ignore\n GM_addStyle(`.filter-${k.toLowerCase().slice(6)} { display: none !important; }`);\n }\n return acc;\n }, {});\n }\n\n filterPublic = (): FilterFunction => {\n return (v: FilterInput) => {\n const isPublic = !this.rules.IS_PRIVATE(v.element as HTMLElement);\n return {\n tag: 'filter-public',\n condition: this.state.filterPublic && isPublic,\n };\n };\n };\n\n filterPrivate = (): FilterFunction => {\n return (v: FilterInput) => {\n const isPrivate = this.rules.IS_PRIVATE(v.element as HTMLElement);\n return {\n tag: 'filter-private',\n condition: this.state.filterPrivate && isPrivate,\n };\n };\n };\n\n filterDuration = (): FilterFunction => {\n return (v: FilterInput) => {\n const notInRange =\n (v.duration as number) < this.state.filterDurationFrom ||\n (v.duration as number) > this.state.filterDurationTo;\n return {\n tag: 'filter-duration',\n condition: this.state.filterDuration && notInRange,\n };\n };\n };\n\n filterExclude = (): FilterFunction => {\n const tags = DataManager.filterDSLToRegex(this.state.filterExcludeWords);\n return (v: FilterInput) => {\n const containTags = tags.some((tag) => tag.test(v.title as string));\n return {\n tag: 'filter-exclude',\n condition: this.state.filterExclude && containTags,\n };\n };\n };\n\n filterInclude = (): FilterFunction => {\n const tags = DataManager.filterDSLToRegex(this.state.filterIncludeWords);\n return (v: FilterInput) => {\n const containTagsNot = tags.some((tag) => !tag.test(v.title as string));\n return {\n tag: 'filter-include',\n condition: this.state.filterInclude && containTagsNot,\n };\n };\n };\n}\n\ninterface IRules {\n GET_THUMBS: (html: HTMLElement) => HTMLElement[];\n THUMB_URL: (thumbElement: HTMLElement) => string;\n THUMB_DATA: (thumbElement: HTMLElement) => { title: string; duration: number };\n THUMB_IMG_DATA: (thumbElement: HTMLElement) => { img: HTMLElement; imgSrc: string };\n CONTAINER: HTMLElement;\n IS_PRIVATE: (element: HTMLElement) => boolean;\n}\n\nexport class DataManager {\n private rules: IRules;\n private state: DataFilterState;\n private data: Map<string, FilterInput>;\n private lazyImgLoader: LazyImgLoader;\n public dataFilters: { [key: string]: () => FilterFunction };\n\n constructor(rules: IRules, state: DataFilterState) {\n this.rules = rules;\n this.state = state;\n this.data = new Map();\n this.lazyImgLoader = new LazyImgLoader(\n (target: Element) => !this.isFiltered(target as HTMLElement),\n );\n this.dataFilters = new DataFilter(rules, state).filters;\n }\n\n static filterDSLToRegex(str: string): RegExp[] {\n const toFullWord = (w: string) => `(^|\\\\ )${w}($|\\\\ )`;\n const str_ = str.replace(/f\\:(\\w+)/g, (_, w) => toFullWord(w));\n return stringToWords(str_).map((expr: string) => new RegExp(expr, 'i'));\n }\n\n isFiltered(el: HTMLElement): boolean {\n return el.className.includes('filtered');\n }\n\n applyFilters = (filters: { [key: string]: boolean }, offset = 0): void => {\n const filtersToApply = Object.keys(filters)\n .filter((k) => Object.hasOwn(this.dataFilters, k))\n .map((k) => this.dataFilters[k]());\n\n if (filtersToApply.length === 0) return;\n\n const updates: (() => void)[] = [];\n let offset_counter = 1;\n for (const v of this.data.values()) {\n if (++offset_counter > offset) {\n for (const f of filtersToApply) {\n const { tag, condition } = f(v as FilterInput);\n updates.push(() => (v.element as HTMLElement).classList.toggle(tag, condition));\n }\n }\n }\n\n requestAnimationFrame(() => {\n updates.forEach((update) => update());\n });\n };\n\n filterAll = (offset?: number): void => {\n const filters = Object.assign(\n {},\n ...Object.keys(this.dataFilters).map((f) => ({\n [f]: this.state[f as keyof DataFilterState],\n })),\n );\n this.applyFilters(filters, offset);\n };\n\n handleLoadedHTML = (\n html: HTMLElement,\n container?: HTMLElement,\n removeDuplicates = false,\n shouldLazify = true,\n ): void => {\n const thumbs = this.rules.GET_THUMBS(html);\n const data_offset = this.data.size;\n\n for (const thumbElement of thumbs) {\n const url = this.rules.THUMB_URL(thumbElement);\n if (!url || this.data.has(url)) {\n if (removeDuplicates) thumbElement.remove();\n continue;\n }\n\n const { title, duration } = this.rules.THUMB_DATA(thumbElement);\n this.data.set(url, { element: thumbElement, duration, title });\n\n if (shouldLazify) {\n const { img, imgSrc } = this.rules.THUMB_IMG_DATA(thumbElement);\n this.lazyImgLoader.lazify(thumbElement, img as HTMLImageElement, imgSrc);\n }\n\n const parent = container || this.rules.CONTAINER;\n if (!parent.contains(thumbElement)) parent.appendChild(thumbElement);\n }\n\n this.filterAll(data_offset);\n };\n}\n","import { fetchHtml } from '../fetch';\nimport { Observer } from '../observers';\n\ninterface IInfiniteScroller {\n delay: number;\n enabled: boolean;\n writeHistory?: boolean;\n paginationOffset: number;\n paginationLast: number;\n paginationElement: HTMLElement;\n paginationUrlGenerator: (offset: number) => string;\n handleHtmlCallback: (document: HTMLElement) => void;\n intersectionObservable?: HTMLElement;\n alternativeGenerator?: () => OffsetGenerator;\n}\n\ninterface GeneratorResult {\n url: string;\n offset: number;\n}\n\ntype OffsetGenerator = Generator<GeneratorResult> | AsyncGenerator<GeneratorResult>;\n\nexport class InfiniteScroller {\n public paginationGenerator: OffsetGenerator;\n public enabled: boolean;\n public delay: number;\n public paginationOffset: number;\n public paginationLast: number;\n public writeHistory: boolean;\n private handleHtmlCallback: (document: HTMLElement) => void;\n\n constructor({\n enabled = true,\n delay = 350,\n writeHistory = false,\n paginationOffset,\n paginationLast,\n paginationElement,\n paginationUrlGenerator,\n handleHtmlCallback,\n alternativeGenerator,\n intersectionObservable,\n }: IInfiniteScroller) {\n this.enabled = enabled;\n this.delay = delay;\n this.writeHistory = writeHistory;\n this.paginationOffset = paginationOffset;\n this.paginationLast = paginationLast;\n this.handleHtmlCallback = handleHtmlCallback;\n\n this.paginationGenerator =\n alternativeGenerator?.() ??\n InfiniteScroller.createPaginationGenerator(\n paginationOffset,\n paginationLast,\n paginationUrlGenerator,\n );\n\n const observable = intersectionObservable || paginationElement;\n Observer.observeWhile(observable, this.generatorConsumer, this.delay);\n }\n\n private onScrollCBs: Array<(scroller: InfiniteScroller) => void> = [];\n\n public onScroll(callback: (scroller: InfiniteScroller) => void, initCall = false) {\n if (initCall) callback(this);\n this.onScrollCBs.push(callback);\n return this;\n }\n\n private _onScroll() {\n this.onScrollCBs.forEach((cb) => cb(this));\n }\n\n generatorConsumer = async () => {\n if (!this.enabled) return false;\n const {\n value: { url, offset } = {},\n done,\n } = await this.paginationGenerator.next();\n if (!done) {\n const nextPageHTML = await fetchHtml(url);\n const prevScrollPos = document.documentElement.scrollTop;\n this.paginationOffset = offset;\n this.handleHtmlCallback(nextPageHTML);\n this._onScroll();\n window.scrollTo(0, prevScrollPos);\n if (this.writeHistory) {\n history.replaceState({}, '', url);\n }\n }\n return !done;\n };\n\n static *createPaginationGenerator(\n currentPage: number,\n totalPages: number,\n generateURL: (offset: number) => string,\n ): OffsetGenerator {\n for (let offset = currentPage + 1; offset <= totalPages; offset++) {\n const url = generateURL(offset);\n yield { url, offset };\n }\n }\n}\n","import { InfiniteScroller } from '../infinite-scroll';\nimport type { RulesHelper } from '../userscript-utils/rules';\n\nexport interface JabroniStore {\n state: Record<string, boolean | string | number>;\n localState: Record<string, boolean | string | number>;\n subscribe: (callback: () => void) => void;\n}\n\nexport function createInfiniteScroller(\n store: JabroniStore,\n handleHtmlCallback: (document: HTMLElement) => void,\n rules: RulesHelper,\n) {\n const enabled = store.state.infiniteScrollEnabled as boolean;\n const iscroller = new InfiniteScroller({\n enabled,\n handleHtmlCallback,\n ...rules,\n }).onScroll(({ paginationLast, paginationOffset }) => {\n store.localState.pagIndexLast = paginationLast;\n store.localState.pagIndexCur = paginationOffset;\n }, true);\n\n store.subscribe(() => {\n iscroller.enabled = store.state.infiniteScrollEnabled as boolean;\n });\n\n return iscroller;\n}\n","import type { InfiniteScroller } from '../infinite-scroll';\nimport type { JabroniStore } from '../jabroni-outfit-wrap';\nimport { createInfiniteScroller } from '../jabroni-outfit-wrap';\nimport { timeToSeconds } from '../parsers';\nimport { sanitizeStr } from '../strings';\n\nexport interface IRulesHelper {\n delay?: number;\n IS_VIDEO_PAGE: boolean | RegExp;\n IS_SEARCH_PAGE: boolean | RegExp;\n THUMB_URL: string | ((thumb: HTMLElement) => string);\n GET_THUMBS: string | ((html: HTMLElement) => Array<HTMLElement>);\n THUMB_DATA:\n | { title: string; uploader?: string; duration?: string }\n | ((thumb: HTMLElement) => { title: string; duration: number });\n THUMB_IMG_DATA:\n | { img?: string; imgSrc?: string; lazyloading?: string }\n | ((thumb: HTMLElement) => { img?: HTMLElement; imgSrc?: string });\n paginationUrlGenerator:\n | ((offset: number) => string)\n | { searchPage?: string; pathnameLast?: boolean };\n paginationElement: string | ((html?: HTMLElement) => HTMLElement);\n paginationOffset: number;\n paginationLast: number;\n CONTAINER: string | ((html?: HTMLElement) => HTMLElement);\n router?: (\n rules: RulesHelper,\n store: JabroniStore,\n handleHtmlCallback: (document: HTMLElement) => void,\n scroller: InfiniteScroller,\n ) => void;\n URL_DATA?: () => {\n paginationOffset: number;\n paginationUrlGenerator: (offset: number) => string;\n };\n}\n\nexport class RulesHelper {\n public delay = 250;\n public IS_VIDEO_PAGE: boolean;\n public IS_SEARCH_PAGE: boolean;\n public paginationElement: HTMLElement;\n public paginationOffset: number;\n public paginationLast: number;\n public URL_DATA:\n | undefined\n | (() => {\n paginationOffset: number;\n paginationUrlGenerator: (offset: number) => string;\n });\n\n constructor(private options: IRulesHelper) {\n this.delay = options?.delay || this.delay;\n\n this.paginationOffset = this.options.paginationOffset;\n this.paginationLast = this.options.paginationLast;\n\n this.IS_VIDEO_PAGE = this._IS_VIDEO_PAGE();\n this.IS_SEARCH_PAGE = this._IS_SEARCH_PAGE();\n\n this.paginationElement = this._paginationElement();\n\n if (options.URL_DATA) {\n this.URL_DATA = options.URL_DATA;\n Object.assign(this, this.URL_DATA());\n }\n }\n\n public router(store: JabroniStore, handleHtmlCallback: (document: HTMLElement) => void): void {\n if (!this.options.router) return;\n const scroller = createInfiniteScroller(store, handleHtmlCallback, this);\n this.options.router(this, store, handleHtmlCallback, scroller);\n }\n\n public paginationUrlGenerator = (offset: number): string => {\n const opt = this.options.paginationUrlGenerator;\n if (typeof opt === 'function') return opt(offset);\n\n const url = new URL(location.href);\n\n if (opt.searchPage) {\n url.searchParams.set(opt.searchPage, offset.toString());\n return url.href;\n }\n\n if (opt.pathnameLast) {\n if (url.pathname === '/') url.pathname = '/1';\n if (/\\d+$/.test(url.pathname)) {\n url.pathname = url.pathname.replace(/\\d+$/, offset.toString());\n } else {\n url.pathname = `${url.pathname}/${offset}`;\n }\n return url.href;\n }\n\n return url.href;\n };\n\n public _IS_VIDEO_PAGE = () => {\n if (typeof this.options.IS_VIDEO_PAGE === 'boolean') {\n return this.options.IS_VIDEO_PAGE;\n }\n return this.options.IS_VIDEO_PAGE.test(location.pathname);\n };\n\n public _IS_SEARCH_PAGE = () => {\n if (typeof this.options.IS_SEARCH_PAGE === 'boolean') {\n return this.options.IS_SEARCH_PAGE;\n }\n return this.options.IS_SEARCH_PAGE.test(location.pathname);\n };\n\n public _paginationElement = (html = document): HTMLElement => {\n if (typeof this.options.paginationElement === 'function') {\n return this.options.paginationElement(html as unknown as HTMLElement);\n }\n return [...html.querySelectorAll(this.options.paginationElement)].pop() as HTMLElement;\n };\n\n public CONTAINER = (html = document): HTMLElement => {\n if (typeof this.options.CONTAINER === 'function') {\n return this.options.CONTAINER(html as unknown as HTMLElement);\n }\n return [...html.querySelectorAll(this.options.CONTAINER)].pop() as HTMLElement;\n };\n\n public THUMB_URL = (thumb: HTMLElement) => {\n if (typeof this.options.THUMB_URL === 'string') {\n return (thumb.querySelector(this.options.THUMB_URL) as HTMLAnchorElement).href || '';\n }\n return this.options.THUMB_URL(thumb);\n };\n\n public GET_THUMBS = (html: HTMLElement) => {\n if (typeof this.options.GET_THUMBS === 'string') {\n return [...html.querySelectorAll(this.options.GET_THUMBS)] as Array<HTMLElement>;\n }\n return this.options.GET_THUMBS(html);\n };\n\n public THUMB_DATA = (thumb: HTMLElement): { title: string; duration: number } => {\n const opt = this.options.THUMB_DATA;\n if (typeof opt === 'function') return opt(thumb);\n\n let title = sanitizeStr((thumb.querySelector(opt.title) as HTMLElement)?.innerText || '');\n\n if (opt.uploader) {\n const uploader = sanitizeStr(\n (thumb.querySelector(opt.title) as HTMLElement)?.innerText || '',\n );\n\n title = `${title} user:${uploader}`;\n }\n\n const duration = !opt.duration\n ? 0\n : timeToSeconds(\n sanitizeStr((thumb.querySelector(opt.duration) as HTMLElement)?.innerText || ''),\n );\n\n return { title, duration };\n };\n\n public THUMB_IMG_DATA = (thumb: HTMLElement) => {\n const opt = this.options.THUMB_IMG_DATA;\n if (typeof opt === 'function') return opt(thumb);\n\n const result = {};\n\n if (opt.img) {\n const img = thumb.querySelector(opt.img) as HTMLImageElement;\n const imgSrc = img.getAttribute(opt.imgSrc || 'data-src') || img.getAttribute('src');\n\n if (opt.lazyloading) {\n img.classList.remove(opt.lazyloading);\n }\n\n Object.assign(result, { img, imgSrc });\n\n if (img.complete && img.getAttribute('src') && !img.src.includes('data:image')) {\n return {};\n }\n } else return {};\n };\n}\n\n// const _3HENTAI_RULES = new RulesHelper({\n// IS_VIDEO_PAGE: /^\\/g\\/\\d+/.test(location.pathname),\n// IS_SEARCH_PAGE: /^\\/search\\//.test(location.pathname),\n// THUMB_URL: 'a',\n// GET_THUMBS: '.doujin-col',\n// THUMB_DATA: { title: '.title' },\n// THUMB_IMG_DATA: { img: 'img', lazyloading: 'lazy' },\n// paginationUrlGenerator: { searchPage: 'page' },\n// paginationElement: '.pagination',\n// paginationOffset: 1,\n// paginationLast: Math.max(\n// ...Array.from(document.querySelectorAll('.pagination .page-link') || [], (e) =>\n// parseInt((e as HTMLElement).innerText),\n// ).filter(Number),\n// 1,\n// ),\n// CONTAINER: '.listing-container',\n\n// /*\n// PARSE LINKS AND PAGINATION FOR IT!!!!\n\n// */\n\n\n// URL_DATA() {\n// const IS_SEARCH_PAGE = /^\\/search\\//.test(location.pathname);\n// const url = new URL(window.location.href);\n\n// let paginationOffset = parseInt(url.searchParams.get('page') || \"1\");\n// let paginationUrlGenerator = (offset: number) => {\n// url.searchParams.set('page', offset.toString());\n// return url.href;\n// };\n\n// if (!IS_SEARCH_PAGE) {\n// paginationOffset = parseInt(url.pathname.match(/\\d+$/)?.[0] || \"1\");\n// if (url.pathname === '/') url.pathname = '/1';\n// paginationUrlGenerator = (offset: number) => {\n// if (/\\d+$/.test(url.pathname)) {\n// url.pathname = url.pathname.replace(/\\d+$/, offset.toString());\n// } else {\n// url.pathname = `${url.pathname}/${offset}`;\n// }\n// return url.href;\n// };\n// }\n\n// return { paginationOffset, paginationUrlGenerator };\n// },\n// router: () => {},\n// });\n\n\n\n// const __NHENTAI_RULES = new RulesHelper({\n// IS_VIDEO_PAGE: /^\\/g\\/\\d+/.test(location.pathname),\n// IS_SEARCH_PAGE: /^\\/search\\//,\n// THUMB_URL: \".cover\",\n// GET_THUMBS: \".gallery\",\n// THUMB_DATA: { title: \".caption\" },\n// THUMB_IMG_DATA: thumb => {\n// const img = thumb.querySelector(\".cover img\")\n// let imgSrc = img.getAttribute(\"data-src\") || img.getAttribute(\"src\") || \"\"\n// if (!/^\\/g\\/\\d+/.test(location.pathname))\n// imgSrc = imgSrc?.replace(\"t5\", \"t3\")\n// img.classList.remove(\"lazyload\")\n// if (\n// img.complete &&\n// img.getAttribute(\"src\") &&\n// !img.src.includes(\"data:image\")\n// ) {\n// return {}\n// }\n// return { img, imgSrc }\n// },\n// paginationUrlGenerator: { searchPage: \"page\" },\n// paginationElement: \".pagination\",\n// paginationOffset:\n// parseInt(new URL(location.href).searchParams.get(\"page\")) || 1,\n// paginationLast: parseInt(\n// document.querySelector(\".pagination .last\")?.href.match(/\\d+/)?.[0] || \"1\"\n// ),\n// CONTAINER: \".index-container, .container\",\n// router: () => {}\n// })\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","../src/data-manager/index.ts","../src/utils/infinite-scroll/index.ts","../src/utils/jabroni-outfit-wrap/index.ts","../src/utils/userscript-utils/rules.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(\n target: Element,\n callback: () => Promise<boolean> | boolean,\n throttleTime: number,\n ) {\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(\n element: HTMLElement | Element, \n callback: () => void,\n throttle = 1000,\n times = Infinity,\n options: Record<string, boolean> = { childList: true, subtree: true, attributes: true }\n) {\n let lastMutationTime: number;\n let timeout: number;\n let times_ = times;\n const observer = new MutationObserver((_mutationList, _observer) => {\n if (times_ !== Infinity && times_ < 1) {\n observer.disconnect();\n return;\n }\n times_--;\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 return observer;\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}\n\nexport function exterminateVideo(video: HTMLVideoElement) {\n video.removeAttribute('src');\n video.load();\n video.remove();\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',\n].join(' ');\n\nexport function fetchWith(\n url: string,\n options: Record<string, boolean> = { html: false, mobile: false },\n) {\n const reqOpts = {};\n if (options.mobile) Object.assign(reqOpts, { headers: new Headers({ 'User-Agent': MOBILE_UA }) });\n return fetch(url, reqOpts)\n .then((r) => r.text())\n .then((r) => (options.html ? parseDom(r) : r));\n}\n\nexport const fetchHtml = (url: string) => fetchWith(url, { html: true }) as Promise<HTMLElement>;\n\nexport const fetchText = (url: string) => fetchWith(url) as Promise<string>;\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","import { LazyImgLoader } from '../utils/observers';\nimport { stringToWords } from '../utils/strings';\n\ninterface DataFilterState {\n filterPublic: boolean;\n filterPrivate: boolean;\n filterHD: boolean;\n filterDuration: boolean;\n filterDurationFrom: number;\n filterDurationTo: number;\n filterExclude: boolean;\n filterExcludeWords: string;\n filterInclude: boolean;\n filterIncludeWords: string;\n}\n\ninterface FilterResult {\n tag: string;\n condition: boolean;\n}\n\ntype FilterInput = Record<string, string | number | boolean | HTMLElement>;\ntype FilterFunction = (v: FilterInput) => FilterResult;\n\nclass DataFilter {\n private state: DataFilterState;\n private rules: IRules;\n public filters: { [key: string]: () => FilterFunction };\n\n constructor(rules: IRules, state: DataFilterState) {\n this.state = state;\n this.rules = rules;\n\n const methods = Object.getOwnPropertyNames(this);\n this.filters = methods.reduce((acc: { [key: string]: () => FilterFunction }, k) => {\n if (k in this.state) {\n acc[k] = this[k as keyof DataFilter] as unknown as () => FilterFunction;\n //@ts-ignore\n GM_addStyle(`.filter-${k.toLowerCase().slice(6)} { display: none !important; }`);\n }\n return acc;\n }, {});\n }\n\n filterPublic = (): FilterFunction => {\n return (v: FilterInput) => {\n const isPublic = !this.rules.IS_PRIVATE(v.element as HTMLElement);\n return {\n tag: 'filter-public',\n condition: this.state.filterPublic && isPublic,\n };\n };\n };\n\n filterPrivate = (): FilterFunction => {\n return (v: FilterInput) => {\n const isPrivate = this.rules.IS_PRIVATE(v.element as HTMLElement);\n return {\n tag: 'filter-private',\n condition: this.state.filterPrivate && isPrivate,\n };\n };\n };\n\n filterHD = (): FilterFunction => {\n return (v: FilterInput) => {\n const isHD = this.rules.IS_HD(v.element as HTMLElement);\n return {\n tag: 'filter-hd',\n condition: this.state.filterHD && isHD,\n };\n };\n };\n\n filterDuration = (): FilterFunction => {\n return (v: FilterInput) => {\n const notInRange =\n (v.duration as number) < this.state.filterDurationFrom ||\n (v.duration as number) > this.state.filterDurationTo;\n return {\n tag: 'filter-duration',\n condition: this.state.filterDuration && notInRange,\n };\n };\n };\n\n filterExclude = (): FilterFunction => {\n const tags = DataManager.filterDSLToRegex(this.state.filterExcludeWords);\n return (v: FilterInput) => {\n const containTags = tags.some((tag) => tag.test(v.title as string));\n return {\n tag: 'filter-exclude',\n condition: this.state.filterExclude && containTags,\n };\n };\n };\n\n filterInclude = (): FilterFunction => {\n const tags = DataManager.filterDSLToRegex(this.state.filterIncludeWords);\n return (v: FilterInput) => {\n const containTagsNot = tags.some((tag) => !tag.test(v.title as string));\n return {\n tag: 'filter-include',\n condition: this.state.filterInclude && containTagsNot,\n };\n };\n };\n}\n\ninterface IRules {\n GET_THUMBS: (html: HTMLElement) => HTMLElement[];\n THUMB_URL: (thumbElement: HTMLElement) => string;\n THUMB_DATA: (thumbElement: HTMLElement) => { title: string; duration: number };\n THUMB_IMG_DATA: (thumbElement: HTMLElement) => { img: HTMLElement; imgSrc: string };\n CONTAINER: HTMLElement;\n IS_PRIVATE: (element: HTMLElement) => boolean;\n IS_HD: (element: HTMLElement) => boolean;\n}\n\nexport class DataManager {\n private rules: IRules;\n private state: DataFilterState;\n private data: Map<string, FilterInput>;\n private lazyImgLoader: LazyImgLoader;\n public dataFilters: { [key: string]: () => FilterFunction };\n\n constructor(rules: IRules, state: DataFilterState) {\n this.rules = rules;\n this.state = state;\n this.data = new Map();\n this.lazyImgLoader = new LazyImgLoader(\n (target: Element) => !this.isFiltered(target as HTMLElement),\n );\n this.dataFilters = new DataFilter(rules, state).filters;\n\n // @ts-ignore\n Object.assign((unsafeWindow || window), {\n sortByViews: this.sort('views'),\n sortByDuration: this.sort('duration'),\n })\n }\n\n static filterDSLToRegex(str: string): RegExp[] {\n const toFullWord = (w: string) => `(^|\\\\ )${w}($|\\\\ )`;\n const str_ = str.replace(/f\\:(\\w+)/g, (_, w) => toFullWord(w));\n return stringToWords(str_).map((expr: string) => new RegExp(expr, 'i'));\n }\n\n isFiltered(el: HTMLElement): boolean {\n return el.className.includes('filtered');\n }\n\n applyFilters = (filters: { [key: string]: boolean }, offset = 0): void => {\n const filtersToApply = Object.keys(filters)\n .filter((k) => Object.hasOwn(this.dataFilters, k))\n .map((k) => this.dataFilters[k]());\n\n if (filtersToApply.length === 0) return;\n\n const updates: (() => void)[] = [];\n let offset_counter = 1;\n for (const v of this.data.values()) {\n if (++offset_counter > offset) {\n for (const f of filtersToApply) {\n const { tag, condition } = f(v as FilterInput);\n updates.push(() => (v.element as HTMLElement).classList.toggle(tag, condition));\n }\n }\n }\n\n requestAnimationFrame(() => {\n updates.forEach((update) => update());\n });\n };\n\n filterAll = (offset?: number): void => {\n const filters = Object.assign(\n {},\n ...Object.keys(this.dataFilters).map((f) => ({\n [f]: this.state[f as keyof DataFilterState],\n })),\n );\n this.applyFilters(filters, offset);\n };\n\n parseData = (\n html: HTMLElement,\n container?: HTMLElement,\n removeDuplicates = false,\n shouldLazify = true,\n ): void => {\n const thumbs = this.rules.GET_THUMBS(html);\n const data_offset = this.data.size;\n\n for (const thumbElement of thumbs) {\n const url = this.rules.THUMB_URL(thumbElement);\n if (!url || this.data.has(url)) {\n if (removeDuplicates) thumbElement.remove();\n continue;\n }\n\n const data = this.rules.THUMB_DATA(thumbElement);\n this.data.set(url, { element: thumbElement, ...data });\n\n if (shouldLazify) {\n const { img, imgSrc } = this.rules.THUMB_IMG_DATA(thumbElement);\n this.lazyImgLoader.lazify(thumbElement, img as HTMLImageElement, imgSrc);\n }\n\n const parent = container || this.rules.CONTAINER;\n if (!parent.contains(thumbElement)) parent.appendChild(thumbElement);\n }\n\n this.filterAll(data_offset);\n };\n\n sort(propName: string) {\n const sorted = Array.from(this.data.keys()).sort((b, a) => {\n return ((this.data.get(a) as any)[propName] as number) -\n ((this.data.get(b) as any)[propName] as number);\n });\n\n const container = (this.data.get(sorted[0]) as any).element.parentElement as HTMLElement;\n\n sorted.forEach(s => {\n const e = (this.data.get(s) as any).element;\n container.append(e);\n });\n }\n}\n","import { fetchHtml } from '../fetch';\nimport { Observer } from '../observers';\n\ninterface IInfiniteScroller {\n delay: number;\n enabled: boolean;\n writeHistory?: boolean;\n paginationOffset: number;\n paginationLast: number;\n paginationElement: HTMLElement;\n paginationUrlGenerator: (offset: number) => string;\n handleHtmlCallback: (document: HTMLElement) => void;\n intersectionObservable?: HTMLElement;\n alternativeGenerator?: () => OffsetGenerator;\n}\n\ninterface GeneratorResult {\n url: string;\n offset: number;\n}\n\ntype OffsetGenerator = Generator<GeneratorResult> | AsyncGenerator<GeneratorResult>;\n\nexport class InfiniteScroller {\n public paginationGenerator: OffsetGenerator;\n public enabled: boolean;\n public delay: number;\n public paginationOffset: number;\n public paginationLast: number;\n public writeHistory: boolean;\n private handleHtmlCallback: (document: HTMLElement) => void;\n\n constructor({\n enabled = true,\n delay = 350,\n writeHistory = false,\n paginationOffset,\n paginationLast,\n paginationElement,\n paginationUrlGenerator,\n handleHtmlCallback,\n alternativeGenerator,\n intersectionObservable,\n }: IInfiniteScroller) {\n this.enabled = enabled;\n this.delay = delay;\n this.writeHistory = writeHistory;\n this.paginationOffset = paginationOffset;\n this.paginationLast = paginationLast;\n this.handleHtmlCallback = handleHtmlCallback;\n\n this.paginationGenerator =\n alternativeGenerator?.() ??\n InfiniteScroller.createPaginationGenerator(\n paginationOffset,\n paginationLast,\n paginationUrlGenerator,\n );\n\n const observable = intersectionObservable || paginationElement;\n Observer.observeWhile(observable, this.generatorConsumer, this.delay);\n }\n\n private onScrollCBs: Array<(scroller: InfiniteScroller) => void> = [];\n\n public onScroll(callback: (scroller: InfiniteScroller) => void, initCall = false) {\n if (initCall) callback(this);\n this.onScrollCBs.push(callback);\n return this;\n }\n\n private _onScroll() {\n this.onScrollCBs.forEach((cb) => cb(this));\n }\n\n generatorConsumer = async () => {\n if (!this.enabled) return false;\n const {\n value: { url, offset } = {},\n done,\n } = await this.paginationGenerator.next();\n if (!done) {\n const nextPageHTML = await fetchHtml(url);\n const prevScrollPos = document.documentElement.scrollTop;\n this.paginationOffset = offset;\n this.handleHtmlCallback(nextPageHTML);\n this._onScroll();\n window.scrollTo(0, prevScrollPos);\n if (this.writeHistory) {\n history.replaceState({}, '', url);\n }\n }\n return !done;\n };\n\n static *createPaginationGenerator(\n currentPage: number,\n totalPages: number,\n generateURL: (offset: number) => string,\n ): OffsetGenerator {\n for (let offset = currentPage + 1; offset <= totalPages; offset++) {\n const url = generateURL(offset);\n yield { url, offset };\n }\n }\n}\n","import { InfiniteScroller } from '../infinite-scroll';\nimport type { RulesHelper } from '../userscript-utils/rules';\n\nexport interface JabroniStore {\n state: Record<string, boolean | string | number>;\n localState: Record<string, boolean | string | number>;\n subscribe: (callback: () => void) => void;\n}\n\nexport function createInfiniteScroller(\n store: JabroniStore,\n handleHtmlCallback: (document: HTMLElement) => void,\n rules: RulesHelper,\n) {\n const enabled = store.state.infiniteScrollEnabled as boolean;\n const iscroller = new InfiniteScroller({\n enabled,\n handleHtmlCallback,\n ...rules,\n }).onScroll(({ paginationLast, paginationOffset }) => {\n store.localState.pagIndexLast = paginationLast;\n store.localState.pagIndexCur = paginationOffset;\n }, true);\n\n store.subscribe(() => {\n iscroller.enabled = store.state.infiniteScrollEnabled as boolean;\n });\n\n return iscroller;\n}\n","import type { InfiniteScroller } from '../infinite-scroll';\nimport type { JabroniStore } from '../jabroni-outfit-wrap';\nimport { createInfiniteScroller } from '../jabroni-outfit-wrap';\nimport { timeToSeconds } from '../parsers';\nimport { sanitizeStr } from '../strings';\n\nexport interface IRulesHelper {\n delay?: number;\n IS_VIDEO_PAGE: boolean | RegExp;\n IS_SEARCH_PAGE: boolean | RegExp;\n THUMB_URL: string | ((thumb: HTMLElement) => string);\n GET_THUMBS: string | ((html: HTMLElement) => Array<HTMLElement>);\n THUMB_DATA:\n | { title: string; uploader?: string; duration?: string }\n | ((thumb: HTMLElement) => { title: string; duration: number });\n THUMB_IMG_DATA:\n | { img?: string; imgSrc?: string; lazyloading?: string }\n | ((thumb: HTMLElement) => { img?: HTMLElement; imgSrc?: string });\n paginationUrlGenerator:\n | ((offset: number) => string)\n | { searchPage?: string; pathnameLast?: boolean };\n paginationElement: string | ((html?: HTMLElement) => HTMLElement);\n paginationOffset: number;\n paginationLast: number;\n CONTAINER: string | ((html?: HTMLElement) => HTMLElement);\n router?: (\n rules: RulesHelper,\n store: JabroniStore,\n handleHtmlCallback: (document: HTMLElement) => void,\n scroller: InfiniteScroller,\n ) => void;\n URL_DATA?: () => {\n paginationOffset: number;\n paginationUrlGenerator: (offset: number) => string;\n };\n}\n\nexport class RulesHelper {\n public delay = 250;\n public IS_VIDEO_PAGE: boolean;\n public IS_SEARCH_PAGE: boolean;\n public paginationElement: HTMLElement;\n public paginationOffset: number;\n public paginationLast: number;\n public URL_DATA:\n | undefined\n | (() => {\n paginationOffset: number;\n paginationUrlGenerator: (offset: number) => string;\n });\n\n constructor(private options: IRulesHelper) {\n this.delay = options?.delay || this.delay;\n\n this.paginationOffset = this.options.paginationOffset;\n this.paginationLast = this.options.paginationLast;\n\n this.IS_VIDEO_PAGE = this._IS_VIDEO_PAGE();\n this.IS_SEARCH_PAGE = this._IS_SEARCH_PAGE();\n\n this.paginationElement = this._paginationElement();\n\n if (options.URL_DATA) {\n this.URL_DATA = options.URL_DATA;\n Object.assign(this, this.URL_DATA());\n }\n }\n\n public router(store: JabroniStore, handleHtmlCallback: (document: HTMLElement) => void): void {\n if (!this.options.router) return;\n const scroller = createInfiniteScroller(store, handleHtmlCallback, this);\n this.options.router(this, store, handleHtmlCallback, scroller);\n }\n\n public paginationUrlGenerator = (offset: number): string => {\n const opt = this.options.paginationUrlGenerator;\n if (typeof opt === 'function') return opt(offset);\n\n const url = new URL(location.href);\n\n if (opt.searchPage) {\n url.searchParams.set(opt.searchPage, offset.toString());\n return url.href;\n }\n\n if (opt.pathnameLast) {\n if (url.pathname === '/') url.pathname = '/1';\n if (/\\d+$/.test(url.pathname)) {\n url.pathname = url.pathname.replace(/\\d+$/, offset.toString());\n } else {\n url.pathname = `${url.pathname}/${offset}`;\n }\n return url.href;\n }\n\n return url.href;\n };\n\n public _IS_VIDEO_PAGE = () => {\n if (typeof this.options.IS_VIDEO_PAGE === 'boolean') {\n return this.options.IS_VIDEO_PAGE;\n }\n return this.options.IS_VIDEO_PAGE.test(location.pathname);\n };\n\n public _IS_SEARCH_PAGE = () => {\n if (typeof this.options.IS_SEARCH_PAGE === 'boolean') {\n return this.options.IS_SEARCH_PAGE;\n }\n return this.options.IS_SEARCH_PAGE.test(location.pathname);\n };\n\n public _paginationElement = (html = document): HTMLElement => {\n if (typeof this.options.paginationElement === 'function') {\n return this.options.paginationElement(html as unknown as HTMLElement);\n }\n return [...html.querySelectorAll(this.options.paginationElement)].pop() as HTMLElement;\n };\n\n public CONTAINER = (html = document): HTMLElement => {\n if (typeof this.options.CONTAINER === 'function') {\n return this.options.CONTAINER(html as unknown as HTMLElement);\n }\n return [...html.querySelectorAll(this.options.CONTAINER)].pop() as HTMLElement;\n };\n\n public THUMB_URL = (thumb: HTMLElement) => {\n if (typeof this.options.THUMB_URL === 'string') {\n return (thumb.querySelector(this.options.THUMB_URL) as HTMLAnchorElement).href || '';\n }\n return this.options.THUMB_URL(thumb);\n };\n\n public GET_THUMBS = (html: HTMLElement) => {\n if (typeof this.options.GET_THUMBS === 'string') {\n return [...html.querySelectorAll(this.options.GET_THUMBS)] as Array<HTMLElement>;\n }\n return this.options.GET_THUMBS(html);\n };\n\n public THUMB_DATA = (thumb: HTMLElement): { title: string; duration: number } => {\n const opt = this.options.THUMB_DATA;\n if (typeof opt === 'function') return opt(thumb);\n\n let title = sanitizeStr((thumb.querySelector(opt.title) as HTMLElement)?.innerText || '');\n\n if (opt.uploader) {\n const uploader = sanitizeStr(\n (thumb.querySelector(opt.title) as HTMLElement)?.innerText || '',\n );\n\n title = `${title} user:${uploader}`;\n }\n\n const duration = !opt.duration\n ? 0\n : timeToSeconds(\n sanitizeStr((thumb.querySelector(opt.duration) as HTMLElement)?.innerText || ''),\n );\n\n return { title, duration };\n };\n\n public THUMB_IMG_DATA = (thumb: HTMLElement) => {\n const opt = this.options.THUMB_IMG_DATA;\n if (typeof opt === 'function') return opt(thumb);\n\n const result = {};\n\n if (opt.img) {\n const img = thumb.querySelector(opt.img) as HTMLImageElement;\n const imgSrc = img.getAttribute(opt.imgSrc || 'data-src') || img.getAttribute('src');\n\n if (opt.lazyloading) {\n img.classList.remove(opt.lazyloading);\n }\n\n Object.assign(result, { img, imgSrc });\n\n if (img.complete && img.getAttribute('src') && !img.src.includes('data:image')) {\n return {};\n }\n } else return {};\n };\n}\n\n// const _3HENTAI_RULES = new RulesHelper({\n// IS_VIDEO_PAGE: /^\\/g\\/\\d+/.test(location.pathname),\n// IS_SEARCH_PAGE: /^\\/search\\//.test(location.pathname),\n// THUMB_URL: 'a',\n// GET_THUMBS: '.doujin-col',\n// THUMB_DATA: { title: '.title' },\n// THUMB_IMG_DATA: { img: 'img', lazyloading: 'lazy' },\n// paginationUrlGenerator: { searchPage: 'page' },\n// paginationElement: '.pagination',\n// paginationOffset: 1,\n// paginationLast: Math.max(\n// ...Array.from(document.querySelectorAll('.pagination .page-link') || [], (e) =>\n// parseInt((e as HTMLElement).innerText),\n// ).filter(Number),\n// 1,\n// ),\n// CONTAINER: '.listing-container',\n\n/*\n PARSE LINKS AND PAGINATION FOR IT!!!!\n\n*/\n\n\n// URL_DATA() {\n// const IS_SEARCH_PAGE = /^\\/search\\//.test(location.pathname);\n// const url = new URL(window.location.href);\n\n// let paginationOffset = parseInt(url.searchParams.get('page') || \"1\");\n// let paginationUrlGenerator = (offset: number) => {\n// url.searchParams.set('page', offset.toString());\n// return url.href;\n// };\n\n// if (!IS_SEARCH_PAGE) {\n// paginationOffset = parseInt(url.pathname.match(/\\d+$/)?.[0] || \"1\");\n// if (url.pathname === '/') url.pathname = '/1';\n// paginationUrlGenerator = (offset: number) => {\n// if (/\\d+$/.test(url.pathname)) {\n// url.pathname = url.pathname.replace(/\\d+$/, offset.toString());\n// } else {\n// url.pathname = `${url.pathname}/${offset}`;\n// }\n// return url.href;\n// };\n// }\n\n// return { paginationOffset, paginationUrlGenerator };\n// },\n// router: () => {},\n// });\n\n\n\n// const __NHENTAI_RULES = new RulesHelper({\n// IS_VIDEO_PAGE: /^\\/g\\/\\d+/.test(location.pathname),\n// IS_SEARCH_PAGE: /^\\/search\\//,\n// THUMB_URL: \".cover\",\n// GET_THUMBS: \".gallery\",\n// THUMB_DATA: { title: \".caption\" },\n// THUMB_IMG_DATA: thumb => {\n// const img = thumb.querySelector(\".cover img\")\n// let imgSrc = img.getAttribute(\"data-src\") || img.getAttribute(\"src\") || \"\"\n// if (!/^\\/g\\/\\d+/.test(location.pathname))\n// imgSrc = imgSrc?.replace(\"t5\", \"t3\")\n// img.classList.remove(\"lazyload\")\n// if (\n// img.complete &&\n// img.getAttribute(\"src\") &&\n// !img.src.includes(\"data:image\")\n// ) {\n// return {}\n// }\n// return { img, imgSrc }\n// },\n// paginationUrlGenerator: { searchPage: \"page\" },\n// paginationElement: \".pagination\",\n// paginationOffset:\n// parseInt(new URL(location.href).searchParams.get(\"page\")) || 1,\n// paginationLast: parseInt(\n// document.querySelector(\".pagination .last\")?.href.match(/\\d+/)?.[0] || \"1\"\n// ),\n// CONTAINER: \".index-container, .container\",\n// router: () => {}\n// }}\n// "],"names":["s","target","observer"],"mappings":"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"}
|
|
@@ -184,6 +184,11 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
184
184
|
});
|
|
185
185
|
});
|
|
186
186
|
}
|
|
187
|
+
function exterminateVideo(video) {
|
|
188
|
+
video.removeAttribute("src");
|
|
189
|
+
video.load();
|
|
190
|
+
video.remove();
|
|
191
|
+
}
|
|
187
192
|
const MOBILE_UA = [
|
|
188
193
|
"Mozilla/5.0 (Linux; Android 10; K)",
|
|
189
194
|
"AppleWebKit/537.36 (KHTML, like Gecko)",
|
|
@@ -323,6 +328,15 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
323
328
|
};
|
|
324
329
|
};
|
|
325
330
|
});
|
|
331
|
+
__publicField(this, "filterHD", () => {
|
|
332
|
+
return (v) => {
|
|
333
|
+
const isHD = this.rules.IS_HD(v.element);
|
|
334
|
+
return {
|
|
335
|
+
tag: "filter-hd",
|
|
336
|
+
condition: this.state.filterHD && isHD
|
|
337
|
+
};
|
|
338
|
+
};
|
|
339
|
+
});
|
|
326
340
|
__publicField(this, "filterDuration", () => {
|
|
327
341
|
return (v) => {
|
|
328
342
|
const notInRange = v.duration < this.state.filterDurationFrom || v.duration > this.state.filterDurationTo;
|
|
@@ -397,7 +411,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
397
411
|
);
|
|
398
412
|
this.applyFilters(filters, offset);
|
|
399
413
|
});
|
|
400
|
-
__publicField(this, "
|
|
414
|
+
__publicField(this, "parseData", (html, container, removeDuplicates = false, shouldLazify = true) => {
|
|
401
415
|
const thumbs = this.rules.GET_THUMBS(html);
|
|
402
416
|
const data_offset = this.data.size;
|
|
403
417
|
for (const thumbElement of thumbs) {
|
|
@@ -406,8 +420,8 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
406
420
|
if (removeDuplicates) thumbElement.remove();
|
|
407
421
|
continue;
|
|
408
422
|
}
|
|
409
|
-
const
|
|
410
|
-
this.data.set(url, { element: thumbElement,
|
|
423
|
+
const data = this.rules.THUMB_DATA(thumbElement);
|
|
424
|
+
this.data.set(url, { element: thumbElement, ...data });
|
|
411
425
|
if (shouldLazify) {
|
|
412
426
|
const { img, imgSrc } = this.rules.THUMB_IMG_DATA(thumbElement);
|
|
413
427
|
this.lazyImgLoader.lazify(thumbElement, img, imgSrc);
|
|
@@ -424,6 +438,10 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
424
438
|
(target) => !this.isFiltered(target)
|
|
425
439
|
);
|
|
426
440
|
this.dataFilters = new DataFilter(rules, state).filters;
|
|
441
|
+
Object.assign(unsafeWindow || window, {
|
|
442
|
+
sortByViews: this.sort("views"),
|
|
443
|
+
sortByDuration: this.sort("duration")
|
|
444
|
+
});
|
|
427
445
|
}
|
|
428
446
|
static filterDSLToRegex(str) {
|
|
429
447
|
const toFullWord = (w) => `(^|\\ )${w}($|\\ )`;
|
|
@@ -433,6 +451,16 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
433
451
|
isFiltered(el) {
|
|
434
452
|
return el.className.includes("filtered");
|
|
435
453
|
}
|
|
454
|
+
sort(propName) {
|
|
455
|
+
const sorted = Array.from(this.data.keys()).sort((b, a) => {
|
|
456
|
+
return this.data.get(a)[propName] - this.data.get(b)[propName];
|
|
457
|
+
});
|
|
458
|
+
const container = this.data.get(sorted[0]).element.parentElement;
|
|
459
|
+
sorted.forEach((s) => {
|
|
460
|
+
const e = this.data.get(s).element;
|
|
461
|
+
container.append(e);
|
|
462
|
+
});
|
|
463
|
+
}
|
|
436
464
|
}
|
|
437
465
|
class InfiniteScroller {
|
|
438
466
|
constructor({
|
|
@@ -645,6 +673,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
645
673
|
exports2.copyAttributes = copyAttributes;
|
|
646
674
|
exports2.createInfiniteScroller = createInfiniteScroller;
|
|
647
675
|
exports2.downloader = downloader;
|
|
676
|
+
exports2.exterminateVideo = exterminateVideo;
|
|
648
677
|
exports2.fetchHtml = fetchHtml;
|
|
649
678
|
exports2.fetchText = fetchText;
|
|
650
679
|
exports2.fetchWith = fetchWith;
|
|
@@ -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","../src/data-manager/index.ts","../src/utils/infinite-scroll/index.ts","../src/utils/jabroni-outfit-wrap/index.ts","../src/utils/userscript-utils/rules.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(\n target: Element,\n callback: () => Promise<boolean> | boolean,\n throttleTime: number,\n ) {\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(\n element: HTMLElement | Element, \n callback: () => void,\n throttle = 1000,\n times = Infinity,\n options: Record<string, boolean> = { childList: true, subtree: true, attributes: true }\n) {\n let lastMutationTime: number;\n let timeout: number;\n let times_ = times;\n const observer = new MutationObserver((_mutationList, _observer) => {\n if (times_ !== Infinity && times_ < 1) {\n observer.disconnect();\n return;\n }\n times_--;\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 return observer;\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',\n].join(' ');\n\nexport function fetchWith(\n url: string,\n options: Record<string, boolean> = { html: false, mobile: false },\n) {\n const reqOpts = {};\n if (options.mobile) Object.assign(reqOpts, { headers: new Headers({ 'User-Agent': MOBILE_UA }) });\n return fetch(url, reqOpts)\n .then((r) => r.text())\n .then((r) => (options.html ? parseDom(r) : r));\n}\n\nexport const fetchHtml = (url: string) => fetchWith(url, { html: true }) as Promise<HTMLElement>;\n\nexport const fetchText = (url: string) => fetchWith(url) as Promise<string>;\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","import { LazyImgLoader } from '../utils/observers';\nimport { stringToWords } from '../utils/strings';\n\ninterface DataFilterState {\n filterPublic: boolean;\n filterPrivate: boolean;\n filterDuration: boolean;\n filterDurationFrom: number;\n filterDurationTo: number;\n filterExclude: boolean;\n filterExcludeWords: string;\n filterInclude: boolean;\n filterIncludeWords: string;\n}\n\ninterface FilterResult {\n tag: string;\n condition: boolean;\n}\n\ntype FilterInput = Record<string, string | number | boolean | HTMLElement>;\ntype FilterFunction = (v: FilterInput) => FilterResult;\n\nclass DataFilter {\n private state: DataFilterState;\n private rules: IRules;\n public filters: { [key: string]: () => FilterFunction };\n\n constructor(rules: IRules, state: DataFilterState) {\n this.state = state;\n this.rules = rules;\n\n const methods = Object.getOwnPropertyNames(this);\n this.filters = methods.reduce((acc: { [key: string]: () => FilterFunction }, k) => {\n if (k in this.state) {\n acc[k] = this[k as keyof DataFilter] as unknown as () => FilterFunction;\n //@ts-ignore\n GM_addStyle(`.filter-${k.toLowerCase().slice(6)} { display: none !important; }`);\n }\n return acc;\n }, {});\n }\n\n filterPublic = (): FilterFunction => {\n return (v: FilterInput) => {\n const isPublic = !this.rules.IS_PRIVATE(v.element as HTMLElement);\n return {\n tag: 'filter-public',\n condition: this.state.filterPublic && isPublic,\n };\n };\n };\n\n filterPrivate = (): FilterFunction => {\n return (v: FilterInput) => {\n const isPrivate = this.rules.IS_PRIVATE(v.element as HTMLElement);\n return {\n tag: 'filter-private',\n condition: this.state.filterPrivate && isPrivate,\n };\n };\n };\n\n filterDuration = (): FilterFunction => {\n return (v: FilterInput) => {\n const notInRange =\n (v.duration as number) < this.state.filterDurationFrom ||\n (v.duration as number) > this.state.filterDurationTo;\n return {\n tag: 'filter-duration',\n condition: this.state.filterDuration && notInRange,\n };\n };\n };\n\n filterExclude = (): FilterFunction => {\n const tags = DataManager.filterDSLToRegex(this.state.filterExcludeWords);\n return (v: FilterInput) => {\n const containTags = tags.some((tag) => tag.test(v.title as string));\n return {\n tag: 'filter-exclude',\n condition: this.state.filterExclude && containTags,\n };\n };\n };\n\n filterInclude = (): FilterFunction => {\n const tags = DataManager.filterDSLToRegex(this.state.filterIncludeWords);\n return (v: FilterInput) => {\n const containTagsNot = tags.some((tag) => !tag.test(v.title as string));\n return {\n tag: 'filter-include',\n condition: this.state.filterInclude && containTagsNot,\n };\n };\n };\n}\n\ninterface IRules {\n GET_THUMBS: (html: HTMLElement) => HTMLElement[];\n THUMB_URL: (thumbElement: HTMLElement) => string;\n THUMB_DATA: (thumbElement: HTMLElement) => { title: string; duration: number };\n THUMB_IMG_DATA: (thumbElement: HTMLElement) => { img: HTMLElement; imgSrc: string };\n CONTAINER: HTMLElement;\n IS_PRIVATE: (element: HTMLElement) => boolean;\n}\n\nexport class DataManager {\n private rules: IRules;\n private state: DataFilterState;\n private data: Map<string, FilterInput>;\n private lazyImgLoader: LazyImgLoader;\n public dataFilters: { [key: string]: () => FilterFunction };\n\n constructor(rules: IRules, state: DataFilterState) {\n this.rules = rules;\n this.state = state;\n this.data = new Map();\n this.lazyImgLoader = new LazyImgLoader(\n (target: Element) => !this.isFiltered(target as HTMLElement),\n );\n this.dataFilters = new DataFilter(rules, state).filters;\n }\n\n static filterDSLToRegex(str: string): RegExp[] {\n const toFullWord = (w: string) => `(^|\\\\ )${w}($|\\\\ )`;\n const str_ = str.replace(/f\\:(\\w+)/g, (_, w) => toFullWord(w));\n return stringToWords(str_).map((expr: string) => new RegExp(expr, 'i'));\n }\n\n isFiltered(el: HTMLElement): boolean {\n return el.className.includes('filtered');\n }\n\n applyFilters = (filters: { [key: string]: boolean }, offset = 0): void => {\n const filtersToApply = Object.keys(filters)\n .filter((k) => Object.hasOwn(this.dataFilters, k))\n .map((k) => this.dataFilters[k]());\n\n if (filtersToApply.length === 0) return;\n\n const updates: (() => void)[] = [];\n let offset_counter = 1;\n for (const v of this.data.values()) {\n if (++offset_counter > offset) {\n for (const f of filtersToApply) {\n const { tag, condition } = f(v as FilterInput);\n updates.push(() => (v.element as HTMLElement).classList.toggle(tag, condition));\n }\n }\n }\n\n requestAnimationFrame(() => {\n updates.forEach((update) => update());\n });\n };\n\n filterAll = (offset?: number): void => {\n const filters = Object.assign(\n {},\n ...Object.keys(this.dataFilters).map((f) => ({\n [f]: this.state[f as keyof DataFilterState],\n })),\n );\n this.applyFilters(filters, offset);\n };\n\n handleLoadedHTML = (\n html: HTMLElement,\n container?: HTMLElement,\n removeDuplicates = false,\n shouldLazify = true,\n ): void => {\n const thumbs = this.rules.GET_THUMBS(html);\n const data_offset = this.data.size;\n\n for (const thumbElement of thumbs) {\n const url = this.rules.THUMB_URL(thumbElement);\n if (!url || this.data.has(url)) {\n if (removeDuplicates) thumbElement.remove();\n continue;\n }\n\n const { title, duration } = this.rules.THUMB_DATA(thumbElement);\n this.data.set(url, { element: thumbElement, duration, title });\n\n if (shouldLazify) {\n const { img, imgSrc } = this.rules.THUMB_IMG_DATA(thumbElement);\n this.lazyImgLoader.lazify(thumbElement, img as HTMLImageElement, imgSrc);\n }\n\n const parent = container || this.rules.CONTAINER;\n if (!parent.contains(thumbElement)) parent.appendChild(thumbElement);\n }\n\n this.filterAll(data_offset);\n };\n}\n","import { fetchHtml } from '../fetch';\nimport { Observer } from '../observers';\n\ninterface IInfiniteScroller {\n delay: number;\n enabled: boolean;\n writeHistory?: boolean;\n paginationOffset: number;\n paginationLast: number;\n paginationElement: HTMLElement;\n paginationUrlGenerator: (offset: number) => string;\n handleHtmlCallback: (document: HTMLElement) => void;\n intersectionObservable?: HTMLElement;\n alternativeGenerator?: () => OffsetGenerator;\n}\n\ninterface GeneratorResult {\n url: string;\n offset: number;\n}\n\ntype OffsetGenerator = Generator<GeneratorResult> | AsyncGenerator<GeneratorResult>;\n\nexport class InfiniteScroller {\n public paginationGenerator: OffsetGenerator;\n public enabled: boolean;\n public delay: number;\n public paginationOffset: number;\n public paginationLast: number;\n public writeHistory: boolean;\n private handleHtmlCallback: (document: HTMLElement) => void;\n\n constructor({\n enabled = true,\n delay = 350,\n writeHistory = false,\n paginationOffset,\n paginationLast,\n paginationElement,\n paginationUrlGenerator,\n handleHtmlCallback,\n alternativeGenerator,\n intersectionObservable,\n }: IInfiniteScroller) {\n this.enabled = enabled;\n this.delay = delay;\n this.writeHistory = writeHistory;\n this.paginationOffset = paginationOffset;\n this.paginationLast = paginationLast;\n this.handleHtmlCallback = handleHtmlCallback;\n\n this.paginationGenerator =\n alternativeGenerator?.() ??\n InfiniteScroller.createPaginationGenerator(\n paginationOffset,\n paginationLast,\n paginationUrlGenerator,\n );\n\n const observable = intersectionObservable || paginationElement;\n Observer.observeWhile(observable, this.generatorConsumer, this.delay);\n }\n\n private onScrollCBs: Array<(scroller: InfiniteScroller) => void> = [];\n\n public onScroll(callback: (scroller: InfiniteScroller) => void, initCall = false) {\n if (initCall) callback(this);\n this.onScrollCBs.push(callback);\n return this;\n }\n\n private _onScroll() {\n this.onScrollCBs.forEach((cb) => cb(this));\n }\n\n generatorConsumer = async () => {\n if (!this.enabled) return false;\n const {\n value: { url, offset } = {},\n done,\n } = await this.paginationGenerator.next();\n if (!done) {\n const nextPageHTML = await fetchHtml(url);\n const prevScrollPos = document.documentElement.scrollTop;\n this.paginationOffset = offset;\n this.handleHtmlCallback(nextPageHTML);\n this._onScroll();\n window.scrollTo(0, prevScrollPos);\n if (this.writeHistory) {\n history.replaceState({}, '', url);\n }\n }\n return !done;\n };\n\n static *createPaginationGenerator(\n currentPage: number,\n totalPages: number,\n generateURL: (offset: number) => string,\n ): OffsetGenerator {\n for (let offset = currentPage + 1; offset <= totalPages; offset++) {\n const url = generateURL(offset);\n yield { url, offset };\n }\n }\n}\n","import { InfiniteScroller } from '../infinite-scroll';\nimport type { RulesHelper } from '../userscript-utils/rules';\n\nexport interface JabroniStore {\n state: Record<string, boolean | string | number>;\n localState: Record<string, boolean | string | number>;\n subscribe: (callback: () => void) => void;\n}\n\nexport function createInfiniteScroller(\n store: JabroniStore,\n handleHtmlCallback: (document: HTMLElement) => void,\n rules: RulesHelper,\n) {\n const enabled = store.state.infiniteScrollEnabled as boolean;\n const iscroller = new InfiniteScroller({\n enabled,\n handleHtmlCallback,\n ...rules,\n }).onScroll(({ paginationLast, paginationOffset }) => {\n store.localState.pagIndexLast = paginationLast;\n store.localState.pagIndexCur = paginationOffset;\n }, true);\n\n store.subscribe(() => {\n iscroller.enabled = store.state.infiniteScrollEnabled as boolean;\n });\n\n return iscroller;\n}\n","import type { InfiniteScroller } from '../infinite-scroll';\nimport type { JabroniStore } from '../jabroni-outfit-wrap';\nimport { createInfiniteScroller } from '../jabroni-outfit-wrap';\nimport { timeToSeconds } from '../parsers';\nimport { sanitizeStr } from '../strings';\n\nexport interface IRulesHelper {\n delay?: number;\n IS_VIDEO_PAGE: boolean | RegExp;\n IS_SEARCH_PAGE: boolean | RegExp;\n THUMB_URL: string | ((thumb: HTMLElement) => string);\n GET_THUMBS: string | ((html: HTMLElement) => Array<HTMLElement>);\n THUMB_DATA:\n | { title: string; uploader?: string; duration?: string }\n | ((thumb: HTMLElement) => { title: string; duration: number });\n THUMB_IMG_DATA:\n | { img?: string; imgSrc?: string; lazyloading?: string }\n | ((thumb: HTMLElement) => { img?: HTMLElement; imgSrc?: string });\n paginationUrlGenerator:\n | ((offset: number) => string)\n | { searchPage?: string; pathnameLast?: boolean };\n paginationElement: string | ((html?: HTMLElement) => HTMLElement);\n paginationOffset: number;\n paginationLast: number;\n CONTAINER: string | ((html?: HTMLElement) => HTMLElement);\n router?: (\n rules: RulesHelper,\n store: JabroniStore,\n handleHtmlCallback: (document: HTMLElement) => void,\n scroller: InfiniteScroller,\n ) => void;\n URL_DATA?: () => {\n paginationOffset: number;\n paginationUrlGenerator: (offset: number) => string;\n };\n}\n\nexport class RulesHelper {\n public delay = 250;\n public IS_VIDEO_PAGE: boolean;\n public IS_SEARCH_PAGE: boolean;\n public paginationElement: HTMLElement;\n public paginationOffset: number;\n public paginationLast: number;\n public URL_DATA:\n | undefined\n | (() => {\n paginationOffset: number;\n paginationUrlGenerator: (offset: number) => string;\n });\n\n constructor(private options: IRulesHelper) {\n this.delay = options?.delay || this.delay;\n\n this.paginationOffset = this.options.paginationOffset;\n this.paginationLast = this.options.paginationLast;\n\n this.IS_VIDEO_PAGE = this._IS_VIDEO_PAGE();\n this.IS_SEARCH_PAGE = this._IS_SEARCH_PAGE();\n\n this.paginationElement = this._paginationElement();\n\n if (options.URL_DATA) {\n this.URL_DATA = options.URL_DATA;\n Object.assign(this, this.URL_DATA());\n }\n }\n\n public router(store: JabroniStore, handleHtmlCallback: (document: HTMLElement) => void): void {\n if (!this.options.router) return;\n const scroller = createInfiniteScroller(store, handleHtmlCallback, this);\n this.options.router(this, store, handleHtmlCallback, scroller);\n }\n\n public paginationUrlGenerator = (offset: number): string => {\n const opt = this.options.paginationUrlGenerator;\n if (typeof opt === 'function') return opt(offset);\n\n const url = new URL(location.href);\n\n if (opt.searchPage) {\n url.searchParams.set(opt.searchPage, offset.toString());\n return url.href;\n }\n\n if (opt.pathnameLast) {\n if (url.pathname === '/') url.pathname = '/1';\n if (/\\d+$/.test(url.pathname)) {\n url.pathname = url.pathname.replace(/\\d+$/, offset.toString());\n } else {\n url.pathname = `${url.pathname}/${offset}`;\n }\n return url.href;\n }\n\n return url.href;\n };\n\n public _IS_VIDEO_PAGE = () => {\n if (typeof this.options.IS_VIDEO_PAGE === 'boolean') {\n return this.options.IS_VIDEO_PAGE;\n }\n return this.options.IS_VIDEO_PAGE.test(location.pathname);\n };\n\n public _IS_SEARCH_PAGE = () => {\n if (typeof this.options.IS_SEARCH_PAGE === 'boolean') {\n return this.options.IS_SEARCH_PAGE;\n }\n return this.options.IS_SEARCH_PAGE.test(location.pathname);\n };\n\n public _paginationElement = (html = document): HTMLElement => {\n if (typeof this.options.paginationElement === 'function') {\n return this.options.paginationElement(html as unknown as HTMLElement);\n }\n return [...html.querySelectorAll(this.options.paginationElement)].pop() as HTMLElement;\n };\n\n public CONTAINER = (html = document): HTMLElement => {\n if (typeof this.options.CONTAINER === 'function') {\n return this.options.CONTAINER(html as unknown as HTMLElement);\n }\n return [...html.querySelectorAll(this.options.CONTAINER)].pop() as HTMLElement;\n };\n\n public THUMB_URL = (thumb: HTMLElement) => {\n if (typeof this.options.THUMB_URL === 'string') {\n return (thumb.querySelector(this.options.THUMB_URL) as HTMLAnchorElement).href || '';\n }\n return this.options.THUMB_URL(thumb);\n };\n\n public GET_THUMBS = (html: HTMLElement) => {\n if (typeof this.options.GET_THUMBS === 'string') {\n return [...html.querySelectorAll(this.options.GET_THUMBS)] as Array<HTMLElement>;\n }\n return this.options.GET_THUMBS(html);\n };\n\n public THUMB_DATA = (thumb: HTMLElement): { title: string; duration: number } => {\n const opt = this.options.THUMB_DATA;\n if (typeof opt === 'function') return opt(thumb);\n\n let title = sanitizeStr((thumb.querySelector(opt.title) as HTMLElement)?.innerText || '');\n\n if (opt.uploader) {\n const uploader = sanitizeStr(\n (thumb.querySelector(opt.title) as HTMLElement)?.innerText || '',\n );\n\n title = `${title} user:${uploader}`;\n }\n\n const duration = !opt.duration\n ? 0\n : timeToSeconds(\n sanitizeStr((thumb.querySelector(opt.duration) as HTMLElement)?.innerText || ''),\n );\n\n return { title, duration };\n };\n\n public THUMB_IMG_DATA = (thumb: HTMLElement) => {\n const opt = this.options.THUMB_IMG_DATA;\n if (typeof opt === 'function') return opt(thumb);\n\n const result = {};\n\n if (opt.img) {\n const img = thumb.querySelector(opt.img) as HTMLImageElement;\n const imgSrc = img.getAttribute(opt.imgSrc || 'data-src') || img.getAttribute('src');\n\n if (opt.lazyloading) {\n img.classList.remove(opt.lazyloading);\n }\n\n Object.assign(result, { img, imgSrc });\n\n if (img.complete && img.getAttribute('src') && !img.src.includes('data:image')) {\n return {};\n }\n } else return {};\n };\n}\n\n// const _3HENTAI_RULES = new RulesHelper({\n// IS_VIDEO_PAGE: /^\\/g\\/\\d+/.test(location.pathname),\n// IS_SEARCH_PAGE: /^\\/search\\//.test(location.pathname),\n// THUMB_URL: 'a',\n// GET_THUMBS: '.doujin-col',\n// THUMB_DATA: { title: '.title' },\n// THUMB_IMG_DATA: { img: 'img', lazyloading: 'lazy' },\n// paginationUrlGenerator: { searchPage: 'page' },\n// paginationElement: '.pagination',\n// paginationOffset: 1,\n// paginationLast: Math.max(\n// ...Array.from(document.querySelectorAll('.pagination .page-link') || [], (e) =>\n// parseInt((e as HTMLElement).innerText),\n// ).filter(Number),\n// 1,\n// ),\n// CONTAINER: '.listing-container',\n\n// /*\n// PARSE LINKS AND PAGINATION FOR IT!!!!\n\n// */\n\n\n// URL_DATA() {\n// const IS_SEARCH_PAGE = /^\\/search\\//.test(location.pathname);\n// const url = new URL(window.location.href);\n\n// let paginationOffset = parseInt(url.searchParams.get('page') || \"1\");\n// let paginationUrlGenerator = (offset: number) => {\n// url.searchParams.set('page', offset.toString());\n// return url.href;\n// };\n\n// if (!IS_SEARCH_PAGE) {\n// paginationOffset = parseInt(url.pathname.match(/\\d+$/)?.[0] || \"1\");\n// if (url.pathname === '/') url.pathname = '/1';\n// paginationUrlGenerator = (offset: number) => {\n// if (/\\d+$/.test(url.pathname)) {\n// url.pathname = url.pathname.replace(/\\d+$/, offset.toString());\n// } else {\n// url.pathname = `${url.pathname}/${offset}`;\n// }\n// return url.href;\n// };\n// }\n\n// return { paginationOffset, paginationUrlGenerator };\n// },\n// router: () => {},\n// });\n\n\n\n// const __NHENTAI_RULES = new RulesHelper({\n// IS_VIDEO_PAGE: /^\\/g\\/\\d+/.test(location.pathname),\n// IS_SEARCH_PAGE: /^\\/search\\//,\n// THUMB_URL: \".cover\",\n// GET_THUMBS: \".gallery\",\n// THUMB_DATA: { title: \".caption\" },\n// THUMB_IMG_DATA: thumb => {\n// const img = thumb.querySelector(\".cover img\")\n// let imgSrc = img.getAttribute(\"data-src\") || img.getAttribute(\"src\") || \"\"\n// if (!/^\\/g\\/\\d+/.test(location.pathname))\n// imgSrc = imgSrc?.replace(\"t5\", \"t3\")\n// img.classList.remove(\"lazyload\")\n// if (\n// img.complete &&\n// img.getAttribute(\"src\") &&\n// !img.src.includes(\"data:image\")\n// ) {\n// return {}\n// }\n// return { img, imgSrc }\n// },\n// paginationUrlGenerator: { searchPage: \"page\" },\n// paginationElement: \".pagination\",\n// paginationOffset:\n// parseInt(new URL(location.href).searchParams.get(\"page\")) || 1,\n// paginationLast: parseInt(\n// document.querySelector(\".pagination .last\")?.href.match(/\\d+/)?.[0] || \"1\"\n// ),\n// CONTAINER: \".index-container, .container\",\n// router: () => {}\n// })\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","../src/data-manager/index.ts","../src/utils/infinite-scroll/index.ts","../src/utils/jabroni-outfit-wrap/index.ts","../src/utils/userscript-utils/rules.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(\n target: Element,\n callback: () => Promise<boolean> | boolean,\n throttleTime: number,\n ) {\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(\n element: HTMLElement | Element, \n callback: () => void,\n throttle = 1000,\n times = Infinity,\n options: Record<string, boolean> = { childList: true, subtree: true, attributes: true }\n) {\n let lastMutationTime: number;\n let timeout: number;\n let times_ = times;\n const observer = new MutationObserver((_mutationList, _observer) => {\n if (times_ !== Infinity && times_ < 1) {\n observer.disconnect();\n return;\n }\n times_--;\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 return observer;\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}\n\nexport function exterminateVideo(video: HTMLVideoElement) {\n video.removeAttribute('src');\n video.load();\n video.remove();\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',\n].join(' ');\n\nexport function fetchWith(\n url: string,\n options: Record<string, boolean> = { html: false, mobile: false },\n) {\n const reqOpts = {};\n if (options.mobile) Object.assign(reqOpts, { headers: new Headers({ 'User-Agent': MOBILE_UA }) });\n return fetch(url, reqOpts)\n .then((r) => r.text())\n .then((r) => (options.html ? parseDom(r) : r));\n}\n\nexport const fetchHtml = (url: string) => fetchWith(url, { html: true }) as Promise<HTMLElement>;\n\nexport const fetchText = (url: string) => fetchWith(url) as Promise<string>;\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","import { LazyImgLoader } from '../utils/observers';\nimport { stringToWords } from '../utils/strings';\n\ninterface DataFilterState {\n filterPublic: boolean;\n filterPrivate: boolean;\n filterHD: boolean;\n filterDuration: boolean;\n filterDurationFrom: number;\n filterDurationTo: number;\n filterExclude: boolean;\n filterExcludeWords: string;\n filterInclude: boolean;\n filterIncludeWords: string;\n}\n\ninterface FilterResult {\n tag: string;\n condition: boolean;\n}\n\ntype FilterInput = Record<string, string | number | boolean | HTMLElement>;\ntype FilterFunction = (v: FilterInput) => FilterResult;\n\nclass DataFilter {\n private state: DataFilterState;\n private rules: IRules;\n public filters: { [key: string]: () => FilterFunction };\n\n constructor(rules: IRules, state: DataFilterState) {\n this.state = state;\n this.rules = rules;\n\n const methods = Object.getOwnPropertyNames(this);\n this.filters = methods.reduce((acc: { [key: string]: () => FilterFunction }, k) => {\n if (k in this.state) {\n acc[k] = this[k as keyof DataFilter] as unknown as () => FilterFunction;\n //@ts-ignore\n GM_addStyle(`.filter-${k.toLowerCase().slice(6)} { display: none !important; }`);\n }\n return acc;\n }, {});\n }\n\n filterPublic = (): FilterFunction => {\n return (v: FilterInput) => {\n const isPublic = !this.rules.IS_PRIVATE(v.element as HTMLElement);\n return {\n tag: 'filter-public',\n condition: this.state.filterPublic && isPublic,\n };\n };\n };\n\n filterPrivate = (): FilterFunction => {\n return (v: FilterInput) => {\n const isPrivate = this.rules.IS_PRIVATE(v.element as HTMLElement);\n return {\n tag: 'filter-private',\n condition: this.state.filterPrivate && isPrivate,\n };\n };\n };\n\n filterHD = (): FilterFunction => {\n return (v: FilterInput) => {\n const isHD = this.rules.IS_HD(v.element as HTMLElement);\n return {\n tag: 'filter-hd',\n condition: this.state.filterHD && isHD,\n };\n };\n };\n\n filterDuration = (): FilterFunction => {\n return (v: FilterInput) => {\n const notInRange =\n (v.duration as number) < this.state.filterDurationFrom ||\n (v.duration as number) > this.state.filterDurationTo;\n return {\n tag: 'filter-duration',\n condition: this.state.filterDuration && notInRange,\n };\n };\n };\n\n filterExclude = (): FilterFunction => {\n const tags = DataManager.filterDSLToRegex(this.state.filterExcludeWords);\n return (v: FilterInput) => {\n const containTags = tags.some((tag) => tag.test(v.title as string));\n return {\n tag: 'filter-exclude',\n condition: this.state.filterExclude && containTags,\n };\n };\n };\n\n filterInclude = (): FilterFunction => {\n const tags = DataManager.filterDSLToRegex(this.state.filterIncludeWords);\n return (v: FilterInput) => {\n const containTagsNot = tags.some((tag) => !tag.test(v.title as string));\n return {\n tag: 'filter-include',\n condition: this.state.filterInclude && containTagsNot,\n };\n };\n };\n}\n\ninterface IRules {\n GET_THUMBS: (html: HTMLElement) => HTMLElement[];\n THUMB_URL: (thumbElement: HTMLElement) => string;\n THUMB_DATA: (thumbElement: HTMLElement) => { title: string; duration: number };\n THUMB_IMG_DATA: (thumbElement: HTMLElement) => { img: HTMLElement; imgSrc: string };\n CONTAINER: HTMLElement;\n IS_PRIVATE: (element: HTMLElement) => boolean;\n IS_HD: (element: HTMLElement) => boolean;\n}\n\nexport class DataManager {\n private rules: IRules;\n private state: DataFilterState;\n private data: Map<string, FilterInput>;\n private lazyImgLoader: LazyImgLoader;\n public dataFilters: { [key: string]: () => FilterFunction };\n\n constructor(rules: IRules, state: DataFilterState) {\n this.rules = rules;\n this.state = state;\n this.data = new Map();\n this.lazyImgLoader = new LazyImgLoader(\n (target: Element) => !this.isFiltered(target as HTMLElement),\n );\n this.dataFilters = new DataFilter(rules, state).filters;\n\n // @ts-ignore\n Object.assign((unsafeWindow || window), {\n sortByViews: this.sort('views'),\n sortByDuration: this.sort('duration'),\n })\n }\n\n static filterDSLToRegex(str: string): RegExp[] {\n const toFullWord = (w: string) => `(^|\\\\ )${w}($|\\\\ )`;\n const str_ = str.replace(/f\\:(\\w+)/g, (_, w) => toFullWord(w));\n return stringToWords(str_).map((expr: string) => new RegExp(expr, 'i'));\n }\n\n isFiltered(el: HTMLElement): boolean {\n return el.className.includes('filtered');\n }\n\n applyFilters = (filters: { [key: string]: boolean }, offset = 0): void => {\n const filtersToApply = Object.keys(filters)\n .filter((k) => Object.hasOwn(this.dataFilters, k))\n .map((k) => this.dataFilters[k]());\n\n if (filtersToApply.length === 0) return;\n\n const updates: (() => void)[] = [];\n let offset_counter = 1;\n for (const v of this.data.values()) {\n if (++offset_counter > offset) {\n for (const f of filtersToApply) {\n const { tag, condition } = f(v as FilterInput);\n updates.push(() => (v.element as HTMLElement).classList.toggle(tag, condition));\n }\n }\n }\n\n requestAnimationFrame(() => {\n updates.forEach((update) => update());\n });\n };\n\n filterAll = (offset?: number): void => {\n const filters = Object.assign(\n {},\n ...Object.keys(this.dataFilters).map((f) => ({\n [f]: this.state[f as keyof DataFilterState],\n })),\n );\n this.applyFilters(filters, offset);\n };\n\n parseData = (\n html: HTMLElement,\n container?: HTMLElement,\n removeDuplicates = false,\n shouldLazify = true,\n ): void => {\n const thumbs = this.rules.GET_THUMBS(html);\n const data_offset = this.data.size;\n\n for (const thumbElement of thumbs) {\n const url = this.rules.THUMB_URL(thumbElement);\n if (!url || this.data.has(url)) {\n if (removeDuplicates) thumbElement.remove();\n continue;\n }\n\n const data = this.rules.THUMB_DATA(thumbElement);\n this.data.set(url, { element: thumbElement, ...data });\n\n if (shouldLazify) {\n const { img, imgSrc } = this.rules.THUMB_IMG_DATA(thumbElement);\n this.lazyImgLoader.lazify(thumbElement, img as HTMLImageElement, imgSrc);\n }\n\n const parent = container || this.rules.CONTAINER;\n if (!parent.contains(thumbElement)) parent.appendChild(thumbElement);\n }\n\n this.filterAll(data_offset);\n };\n\n sort(propName: string) {\n const sorted = Array.from(this.data.keys()).sort((b, a) => {\n return ((this.data.get(a) as any)[propName] as number) -\n ((this.data.get(b) as any)[propName] as number);\n });\n\n const container = (this.data.get(sorted[0]) as any).element.parentElement as HTMLElement;\n\n sorted.forEach(s => {\n const e = (this.data.get(s) as any).element;\n container.append(e);\n });\n }\n}\n","import { fetchHtml } from '../fetch';\nimport { Observer } from '../observers';\n\ninterface IInfiniteScroller {\n delay: number;\n enabled: boolean;\n writeHistory?: boolean;\n paginationOffset: number;\n paginationLast: number;\n paginationElement: HTMLElement;\n paginationUrlGenerator: (offset: number) => string;\n handleHtmlCallback: (document: HTMLElement) => void;\n intersectionObservable?: HTMLElement;\n alternativeGenerator?: () => OffsetGenerator;\n}\n\ninterface GeneratorResult {\n url: string;\n offset: number;\n}\n\ntype OffsetGenerator = Generator<GeneratorResult> | AsyncGenerator<GeneratorResult>;\n\nexport class InfiniteScroller {\n public paginationGenerator: OffsetGenerator;\n public enabled: boolean;\n public delay: number;\n public paginationOffset: number;\n public paginationLast: number;\n public writeHistory: boolean;\n private handleHtmlCallback: (document: HTMLElement) => void;\n\n constructor({\n enabled = true,\n delay = 350,\n writeHistory = false,\n paginationOffset,\n paginationLast,\n paginationElement,\n paginationUrlGenerator,\n handleHtmlCallback,\n alternativeGenerator,\n intersectionObservable,\n }: IInfiniteScroller) {\n this.enabled = enabled;\n this.delay = delay;\n this.writeHistory = writeHistory;\n this.paginationOffset = paginationOffset;\n this.paginationLast = paginationLast;\n this.handleHtmlCallback = handleHtmlCallback;\n\n this.paginationGenerator =\n alternativeGenerator?.() ??\n InfiniteScroller.createPaginationGenerator(\n paginationOffset,\n paginationLast,\n paginationUrlGenerator,\n );\n\n const observable = intersectionObservable || paginationElement;\n Observer.observeWhile(observable, this.generatorConsumer, this.delay);\n }\n\n private onScrollCBs: Array<(scroller: InfiniteScroller) => void> = [];\n\n public onScroll(callback: (scroller: InfiniteScroller) => void, initCall = false) {\n if (initCall) callback(this);\n this.onScrollCBs.push(callback);\n return this;\n }\n\n private _onScroll() {\n this.onScrollCBs.forEach((cb) => cb(this));\n }\n\n generatorConsumer = async () => {\n if (!this.enabled) return false;\n const {\n value: { url, offset } = {},\n done,\n } = await this.paginationGenerator.next();\n if (!done) {\n const nextPageHTML = await fetchHtml(url);\n const prevScrollPos = document.documentElement.scrollTop;\n this.paginationOffset = offset;\n this.handleHtmlCallback(nextPageHTML);\n this._onScroll();\n window.scrollTo(0, prevScrollPos);\n if (this.writeHistory) {\n history.replaceState({}, '', url);\n }\n }\n return !done;\n };\n\n static *createPaginationGenerator(\n currentPage: number,\n totalPages: number,\n generateURL: (offset: number) => string,\n ): OffsetGenerator {\n for (let offset = currentPage + 1; offset <= totalPages; offset++) {\n const url = generateURL(offset);\n yield { url, offset };\n }\n }\n}\n","import { InfiniteScroller } from '../infinite-scroll';\nimport type { RulesHelper } from '../userscript-utils/rules';\n\nexport interface JabroniStore {\n state: Record<string, boolean | string | number>;\n localState: Record<string, boolean | string | number>;\n subscribe: (callback: () => void) => void;\n}\n\nexport function createInfiniteScroller(\n store: JabroniStore,\n handleHtmlCallback: (document: HTMLElement) => void,\n rules: RulesHelper,\n) {\n const enabled = store.state.infiniteScrollEnabled as boolean;\n const iscroller = new InfiniteScroller({\n enabled,\n handleHtmlCallback,\n ...rules,\n }).onScroll(({ paginationLast, paginationOffset }) => {\n store.localState.pagIndexLast = paginationLast;\n store.localState.pagIndexCur = paginationOffset;\n }, true);\n\n store.subscribe(() => {\n iscroller.enabled = store.state.infiniteScrollEnabled as boolean;\n });\n\n return iscroller;\n}\n","import type { InfiniteScroller } from '../infinite-scroll';\nimport type { JabroniStore } from '../jabroni-outfit-wrap';\nimport { createInfiniteScroller } from '../jabroni-outfit-wrap';\nimport { timeToSeconds } from '../parsers';\nimport { sanitizeStr } from '../strings';\n\nexport interface IRulesHelper {\n delay?: number;\n IS_VIDEO_PAGE: boolean | RegExp;\n IS_SEARCH_PAGE: boolean | RegExp;\n THUMB_URL: string | ((thumb: HTMLElement) => string);\n GET_THUMBS: string | ((html: HTMLElement) => Array<HTMLElement>);\n THUMB_DATA:\n | { title: string; uploader?: string; duration?: string }\n | ((thumb: HTMLElement) => { title: string; duration: number });\n THUMB_IMG_DATA:\n | { img?: string; imgSrc?: string; lazyloading?: string }\n | ((thumb: HTMLElement) => { img?: HTMLElement; imgSrc?: string });\n paginationUrlGenerator:\n | ((offset: number) => string)\n | { searchPage?: string; pathnameLast?: boolean };\n paginationElement: string | ((html?: HTMLElement) => HTMLElement);\n paginationOffset: number;\n paginationLast: number;\n CONTAINER: string | ((html?: HTMLElement) => HTMLElement);\n router?: (\n rules: RulesHelper,\n store: JabroniStore,\n handleHtmlCallback: (document: HTMLElement) => void,\n scroller: InfiniteScroller,\n ) => void;\n URL_DATA?: () => {\n paginationOffset: number;\n paginationUrlGenerator: (offset: number) => string;\n };\n}\n\nexport class RulesHelper {\n public delay = 250;\n public IS_VIDEO_PAGE: boolean;\n public IS_SEARCH_PAGE: boolean;\n public paginationElement: HTMLElement;\n public paginationOffset: number;\n public paginationLast: number;\n public URL_DATA:\n | undefined\n | (() => {\n paginationOffset: number;\n paginationUrlGenerator: (offset: number) => string;\n });\n\n constructor(private options: IRulesHelper) {\n this.delay = options?.delay || this.delay;\n\n this.paginationOffset = this.options.paginationOffset;\n this.paginationLast = this.options.paginationLast;\n\n this.IS_VIDEO_PAGE = this._IS_VIDEO_PAGE();\n this.IS_SEARCH_PAGE = this._IS_SEARCH_PAGE();\n\n this.paginationElement = this._paginationElement();\n\n if (options.URL_DATA) {\n this.URL_DATA = options.URL_DATA;\n Object.assign(this, this.URL_DATA());\n }\n }\n\n public router(store: JabroniStore, handleHtmlCallback: (document: HTMLElement) => void): void {\n if (!this.options.router) return;\n const scroller = createInfiniteScroller(store, handleHtmlCallback, this);\n this.options.router(this, store, handleHtmlCallback, scroller);\n }\n\n public paginationUrlGenerator = (offset: number): string => {\n const opt = this.options.paginationUrlGenerator;\n if (typeof opt === 'function') return opt(offset);\n\n const url = new URL(location.href);\n\n if (opt.searchPage) {\n url.searchParams.set(opt.searchPage, offset.toString());\n return url.href;\n }\n\n if (opt.pathnameLast) {\n if (url.pathname === '/') url.pathname = '/1';\n if (/\\d+$/.test(url.pathname)) {\n url.pathname = url.pathname.replace(/\\d+$/, offset.toString());\n } else {\n url.pathname = `${url.pathname}/${offset}`;\n }\n return url.href;\n }\n\n return url.href;\n };\n\n public _IS_VIDEO_PAGE = () => {\n if (typeof this.options.IS_VIDEO_PAGE === 'boolean') {\n return this.options.IS_VIDEO_PAGE;\n }\n return this.options.IS_VIDEO_PAGE.test(location.pathname);\n };\n\n public _IS_SEARCH_PAGE = () => {\n if (typeof this.options.IS_SEARCH_PAGE === 'boolean') {\n return this.options.IS_SEARCH_PAGE;\n }\n return this.options.IS_SEARCH_PAGE.test(location.pathname);\n };\n\n public _paginationElement = (html = document): HTMLElement => {\n if (typeof this.options.paginationElement === 'function') {\n return this.options.paginationElement(html as unknown as HTMLElement);\n }\n return [...html.querySelectorAll(this.options.paginationElement)].pop() as HTMLElement;\n };\n\n public CONTAINER = (html = document): HTMLElement => {\n if (typeof this.options.CONTAINER === 'function') {\n return this.options.CONTAINER(html as unknown as HTMLElement);\n }\n return [...html.querySelectorAll(this.options.CONTAINER)].pop() as HTMLElement;\n };\n\n public THUMB_URL = (thumb: HTMLElement) => {\n if (typeof this.options.THUMB_URL === 'string') {\n return (thumb.querySelector(this.options.THUMB_URL) as HTMLAnchorElement).href || '';\n }\n return this.options.THUMB_URL(thumb);\n };\n\n public GET_THUMBS = (html: HTMLElement) => {\n if (typeof this.options.GET_THUMBS === 'string') {\n return [...html.querySelectorAll(this.options.GET_THUMBS)] as Array<HTMLElement>;\n }\n return this.options.GET_THUMBS(html);\n };\n\n public THUMB_DATA = (thumb: HTMLElement): { title: string; duration: number } => {\n const opt = this.options.THUMB_DATA;\n if (typeof opt === 'function') return opt(thumb);\n\n let title = sanitizeStr((thumb.querySelector(opt.title) as HTMLElement)?.innerText || '');\n\n if (opt.uploader) {\n const uploader = sanitizeStr(\n (thumb.querySelector(opt.title) as HTMLElement)?.innerText || '',\n );\n\n title = `${title} user:${uploader}`;\n }\n\n const duration = !opt.duration\n ? 0\n : timeToSeconds(\n sanitizeStr((thumb.querySelector(opt.duration) as HTMLElement)?.innerText || ''),\n );\n\n return { title, duration };\n };\n\n public THUMB_IMG_DATA = (thumb: HTMLElement) => {\n const opt = this.options.THUMB_IMG_DATA;\n if (typeof opt === 'function') return opt(thumb);\n\n const result = {};\n\n if (opt.img) {\n const img = thumb.querySelector(opt.img) as HTMLImageElement;\n const imgSrc = img.getAttribute(opt.imgSrc || 'data-src') || img.getAttribute('src');\n\n if (opt.lazyloading) {\n img.classList.remove(opt.lazyloading);\n }\n\n Object.assign(result, { img, imgSrc });\n\n if (img.complete && img.getAttribute('src') && !img.src.includes('data:image')) {\n return {};\n }\n } else return {};\n };\n}\n\n// const _3HENTAI_RULES = new RulesHelper({\n// IS_VIDEO_PAGE: /^\\/g\\/\\d+/.test(location.pathname),\n// IS_SEARCH_PAGE: /^\\/search\\//.test(location.pathname),\n// THUMB_URL: 'a',\n// GET_THUMBS: '.doujin-col',\n// THUMB_DATA: { title: '.title' },\n// THUMB_IMG_DATA: { img: 'img', lazyloading: 'lazy' },\n// paginationUrlGenerator: { searchPage: 'page' },\n// paginationElement: '.pagination',\n// paginationOffset: 1,\n// paginationLast: Math.max(\n// ...Array.from(document.querySelectorAll('.pagination .page-link') || [], (e) =>\n// parseInt((e as HTMLElement).innerText),\n// ).filter(Number),\n// 1,\n// ),\n// CONTAINER: '.listing-container',\n\n/*\n PARSE LINKS AND PAGINATION FOR IT!!!!\n\n*/\n\n\n// URL_DATA() {\n// const IS_SEARCH_PAGE = /^\\/search\\//.test(location.pathname);\n// const url = new URL(window.location.href);\n\n// let paginationOffset = parseInt(url.searchParams.get('page') || \"1\");\n// let paginationUrlGenerator = (offset: number) => {\n// url.searchParams.set('page', offset.toString());\n// return url.href;\n// };\n\n// if (!IS_SEARCH_PAGE) {\n// paginationOffset = parseInt(url.pathname.match(/\\d+$/)?.[0] || \"1\");\n// if (url.pathname === '/') url.pathname = '/1';\n// paginationUrlGenerator = (offset: number) => {\n// if (/\\d+$/.test(url.pathname)) {\n// url.pathname = url.pathname.replace(/\\d+$/, offset.toString());\n// } else {\n// url.pathname = `${url.pathname}/${offset}`;\n// }\n// return url.href;\n// };\n// }\n\n// return { paginationOffset, paginationUrlGenerator };\n// },\n// router: () => {},\n// });\n\n\n\n// const __NHENTAI_RULES = new RulesHelper({\n// IS_VIDEO_PAGE: /^\\/g\\/\\d+/.test(location.pathname),\n// IS_SEARCH_PAGE: /^\\/search\\//,\n// THUMB_URL: \".cover\",\n// GET_THUMBS: \".gallery\",\n// THUMB_DATA: { title: \".caption\" },\n// THUMB_IMG_DATA: thumb => {\n// const img = thumb.querySelector(\".cover img\")\n// let imgSrc = img.getAttribute(\"data-src\") || img.getAttribute(\"src\") || \"\"\n// if (!/^\\/g\\/\\d+/.test(location.pathname))\n// imgSrc = imgSrc?.replace(\"t5\", \"t3\")\n// img.classList.remove(\"lazyload\")\n// if (\n// img.complete &&\n// img.getAttribute(\"src\") &&\n// !img.src.includes(\"data:image\")\n// ) {\n// return {}\n// }\n// return { img, imgSrc }\n// },\n// paginationUrlGenerator: { searchPage: \"page\" },\n// paginationElement: \".pagination\",\n// paginationOffset:\n// parseInt(new URL(location.href).searchParams.get(\"page\")) || 1,\n// paginationLast: parseInt(\n// document.querySelector(\".pagination .last\")?.href.match(/\\d+/)?.[0] || \"1\"\n// ),\n// CONTAINER: \".index-container, .container\",\n// router: () => {}\n// }}\n// "],"names":["s","target","observer"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -31,6 +31,7 @@ export declare function createInfiniteScroller(store: JabroniStore, handleHtmlCa
|
|
|
31
31
|
declare interface DataFilterState {
|
|
32
32
|
filterPublic: boolean;
|
|
33
33
|
filterPrivate: boolean;
|
|
34
|
+
filterHD: boolean;
|
|
34
35
|
filterDuration: boolean;
|
|
35
36
|
filterDurationFrom: number;
|
|
36
37
|
filterDurationTo: number;
|
|
@@ -55,7 +56,8 @@ export declare class DataManager {
|
|
|
55
56
|
[key: string]: boolean;
|
|
56
57
|
}, offset?: number) => void;
|
|
57
58
|
filterAll: (offset?: number) => void;
|
|
58
|
-
|
|
59
|
+
parseData: (html: HTMLElement, container?: HTMLElement, removeDuplicates?: boolean, shouldLazify?: boolean) => void;
|
|
60
|
+
sort(propName: string): void;
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
export declare function downloader(options?: {
|
|
@@ -65,6 +67,8 @@ export declare function downloader(options?: {
|
|
|
65
67
|
cbBefore: () => void;
|
|
66
68
|
}): void;
|
|
67
69
|
|
|
70
|
+
export declare function exterminateVideo(video: HTMLVideoElement): void;
|
|
71
|
+
|
|
68
72
|
export declare const fetchHtml: (url: string) => Promise<HTMLElement>;
|
|
69
73
|
|
|
70
74
|
export declare const fetchText: (url: string) => Promise<string>;
|
|
@@ -131,6 +135,7 @@ declare interface IRules {
|
|
|
131
135
|
};
|
|
132
136
|
CONTAINER: HTMLElement;
|
|
133
137
|
IS_PRIVATE: (element: HTMLElement) => boolean;
|
|
138
|
+
IS_HD: (element: HTMLElement) => boolean;
|
|
134
139
|
}
|
|
135
140
|
|
|
136
141
|
export declare interface IRulesHelper {
|
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.3.
|
|
4
|
+
"version": "1.3.8",
|
|
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)",
|
|
@@ -4,6 +4,7 @@ import { stringToWords } from '../utils/strings';
|
|
|
4
4
|
interface DataFilterState {
|
|
5
5
|
filterPublic: boolean;
|
|
6
6
|
filterPrivate: boolean;
|
|
7
|
+
filterHD: boolean;
|
|
7
8
|
filterDuration: boolean;
|
|
8
9
|
filterDurationFrom: number;
|
|
9
10
|
filterDurationTo: number;
|
|
@@ -61,6 +62,16 @@ class DataFilter {
|
|
|
61
62
|
};
|
|
62
63
|
};
|
|
63
64
|
|
|
65
|
+
filterHD = (): FilterFunction => {
|
|
66
|
+
return (v: FilterInput) => {
|
|
67
|
+
const isHD = this.rules.IS_HD(v.element as HTMLElement);
|
|
68
|
+
return {
|
|
69
|
+
tag: 'filter-hd',
|
|
70
|
+
condition: this.state.filterHD && isHD,
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
|
|
64
75
|
filterDuration = (): FilterFunction => {
|
|
65
76
|
return (v: FilterInput) => {
|
|
66
77
|
const notInRange =
|
|
@@ -103,6 +114,7 @@ interface IRules {
|
|
|
103
114
|
THUMB_IMG_DATA: (thumbElement: HTMLElement) => { img: HTMLElement; imgSrc: string };
|
|
104
115
|
CONTAINER: HTMLElement;
|
|
105
116
|
IS_PRIVATE: (element: HTMLElement) => boolean;
|
|
117
|
+
IS_HD: (element: HTMLElement) => boolean;
|
|
106
118
|
}
|
|
107
119
|
|
|
108
120
|
export class DataManager {
|
|
@@ -120,6 +132,12 @@ export class DataManager {
|
|
|
120
132
|
(target: Element) => !this.isFiltered(target as HTMLElement),
|
|
121
133
|
);
|
|
122
134
|
this.dataFilters = new DataFilter(rules, state).filters;
|
|
135
|
+
|
|
136
|
+
// @ts-ignore
|
|
137
|
+
Object.assign((unsafeWindow || window), {
|
|
138
|
+
sortByViews: this.sort('views'),
|
|
139
|
+
sortByDuration: this.sort('duration'),
|
|
140
|
+
})
|
|
123
141
|
}
|
|
124
142
|
|
|
125
143
|
static filterDSLToRegex(str: string): RegExp[] {
|
|
@@ -165,7 +183,7 @@ export class DataManager {
|
|
|
165
183
|
this.applyFilters(filters, offset);
|
|
166
184
|
};
|
|
167
185
|
|
|
168
|
-
|
|
186
|
+
parseData = (
|
|
169
187
|
html: HTMLElement,
|
|
170
188
|
container?: HTMLElement,
|
|
171
189
|
removeDuplicates = false,
|
|
@@ -181,8 +199,8 @@ export class DataManager {
|
|
|
181
199
|
continue;
|
|
182
200
|
}
|
|
183
201
|
|
|
184
|
-
const
|
|
185
|
-
this.data.set(url, { element: thumbElement,
|
|
202
|
+
const data = this.rules.THUMB_DATA(thumbElement);
|
|
203
|
+
this.data.set(url, { element: thumbElement, ...data });
|
|
186
204
|
|
|
187
205
|
if (shouldLazify) {
|
|
188
206
|
const { img, imgSrc } = this.rules.THUMB_IMG_DATA(thumbElement);
|
|
@@ -195,4 +213,18 @@ export class DataManager {
|
|
|
195
213
|
|
|
196
214
|
this.filterAll(data_offset);
|
|
197
215
|
};
|
|
216
|
+
|
|
217
|
+
sort(propName: string) {
|
|
218
|
+
const sorted = Array.from(this.data.keys()).sort((b, a) => {
|
|
219
|
+
return ((this.data.get(a) as any)[propName] as number) -
|
|
220
|
+
((this.data.get(b) as any)[propName] as number);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
const container = (this.data.get(sorted[0]) as any).element.parentElement as HTMLElement;
|
|
224
|
+
|
|
225
|
+
sorted.forEach(s => {
|
|
226
|
+
const e = (this.data.get(s) as any).element;
|
|
227
|
+
container.append(e);
|
|
228
|
+
});
|
|
229
|
+
}
|
|
198
230
|
}
|
|
@@ -12,9 +12,6 @@ export function createInfiniteScroller(
|
|
|
12
12
|
handleHtmlCallback: (document: HTMLElement) => void,
|
|
13
13
|
rules: RulesHelper,
|
|
14
14
|
) {
|
|
15
|
-
//@ts-ignore
|
|
16
|
-
if (!store.localState) store.localState = store.stateLocale;
|
|
17
|
-
|
|
18
15
|
const enabled = store.state.infiniteScrollEnabled as boolean;
|
|
19
16
|
const iscroller = new InfiniteScroller({
|
|
20
17
|
enabled,
|