billy-herrington-utils 1.4.2 → 1.4.4

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.
@@ -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}\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 [window, unsafeWindow || ({})].forEach(w => {\n Object.assign(w, {\n sortByViews: () => this.sort('view'),\n sortByDuration: () => this.sort('duration'),\n });\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 if (this.data.size < 2) return;\n\n const sorted = Array.from(this.data.keys()).sort((b, a) => {\n return ((this.data.get(a) as FilterInput)[propName] as number) -\n ((this.data.get(b) as FilterInput)[propName] as number);\n });\n\n const container = ((this.data.get(sorted[0]) as FilterInput).element as HTMLElement).parentElement as HTMLElement;\n\n sorted.forEach(s => {\n const e = (this.data.get(s) as FilterInput).element as HTMLElement;\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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"}
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"],"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 const paramsStr = decodeURI(str.trim()).split(';');\n return paramsStr.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 public filters: { [key: string]: () => FilterFunction };\n\n constructor(private rules: IRules, private state: DataFilterState) {\n this.state = state;\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.isPrivate(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.isPrivate(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.isHD(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 getThumbs: (html: HTMLElement) => HTMLElement[];\n getThumbUrl: (thumbElement: HTMLElement) => string;\n getThumbData: (thumbElement: HTMLElement) => { title: string; duration: number };\n getThumbImgData: (thumbElement: HTMLElement) => { img: HTMLElement; imgSrc: string };\n container: HTMLElement;\n isPrivate: (element: HTMLElement) => boolean;\n isHD: (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 [window, unsafeWindow || ({})].forEach(w => {\n Object.assign(w, {\n sortByViews: () => this.sort('view'),\n sortByDuration: () => this.sort('duration'),\n });\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.getThumbs(html);\n const data_offset = this.data.size;\n\n for (const thumbElement of thumbs) {\n const url = this.rules.getThumbUrl(thumbElement);\n if (!url || this.data.has(url)) {\n if (removeDuplicates) thumbElement.remove();\n continue;\n }\n\n const data = this.rules.getThumbData(thumbElement);\n this.data.set(url, { element: thumbElement, ...data });\n\n if (shouldLazify) {\n const { img, imgSrc } = this.rules.getThumbImgData(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 if (this.data.size < 2) return;\n\n const sorted = Array.from(this.data.keys()).sort((b, a) => {\n return ((this.data.get(a) as FilterInput)[propName] as number) -\n ((this.data.get(b) as FilterInput)[propName] as number);\n });\n\n const container = ((this.data.get(sorted[0]) as FilterInput).element as HTMLElement).parentElement as HTMLElement;\n\n sorted.forEach(s => {\n const e = (this.data.get(s) as FilterInput).element as HTMLElement;\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 { PaginationStrategy } from '../userscript-utils/pagination-strategies';\n\ninterface IRules {\n paginationStrategy: PaginationStrategy,\n delay: number, \n paginationOffset: number, \n paginationLast: number, \n paginationElement: HTMLElement,\n paginationUrlGenerator: (n: number) => string;\n}\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: IRules,\n) {\n const enabled = store.state.infiniteScrollEnabled as boolean;\n \n rules.paginationOffset = rules.paginationStrategy.getPaginationOffset();\n rules.paginationLast = rules.paginationStrategy.getPaginationLast();\n rules.paginationUrlGenerator = rules.paginationStrategy.getPaginationUrlGenerator();\n rules.paginationElement = rules.paginationStrategy.getPaginationElement();\n\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"],"names":["s","target","observer"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -26,7 +26,7 @@ export declare function computeAsyncOneAtTime(iterable: Iterable<() => Promise<v
26
26
 
27
27
  export declare function copyAttributes(target: HTMLElement | Element, source: HTMLElement | Element): void;
28
28
 
29
- export declare function createInfiniteScroller(store: JabroniStore, handleHtmlCallback: (document: HTMLElement) => void, rules: RulesHelper): InfiniteScroller;
29
+ export declare function createInfiniteScroller(store: JabroniStore, handleHtmlCallback: (document: HTMLElement) => void, rules: IRules_2): InfiniteScroller;
30
30
 
31
31
  declare interface DataFilterState {
32
32
  filterPublic: boolean;
@@ -123,56 +123,28 @@ export declare class InfiniteScroller {
123
123
  }
124
124
 
125
125
  declare interface IRules {
126
- GET_THUMBS: (html: HTMLElement) => HTMLElement[];
127
- THUMB_URL: (thumbElement: HTMLElement) => string;
128
- THUMB_DATA: (thumbElement: HTMLElement) => {
126
+ getThumbs: (html: HTMLElement) => HTMLElement[];
127
+ getThumbUrl: (thumbElement: HTMLElement) => string;
128
+ getThumbData: (thumbElement: HTMLElement) => {
129
129
  title: string;
130
130
  duration: number;
131
131
  };
132
- THUMB_IMG_DATA: (thumbElement: HTMLElement) => {
132
+ getThumbImgData: (thumbElement: HTMLElement) => {
133
133
  img: HTMLElement;
134
134
  imgSrc: string;
135
135
  };
136
- CONTAINER: HTMLElement;
137
- IS_PRIVATE: (element: HTMLElement) => boolean;
138
- IS_HD: (element: HTMLElement) => boolean;
136
+ container: HTMLElement;
137
+ isPrivate: (element: HTMLElement) => boolean;
138
+ isHD: (element: HTMLElement) => boolean;
139
139
  }
140
140
 
141
- export declare interface IRulesHelper {
142
- delay?: number;
143
- IS_VIDEO_PAGE: boolean | RegExp;
144
- IS_SEARCH_PAGE: boolean | RegExp;
145
- THUMB_URL: string | ((thumb: HTMLElement) => string);
146
- GET_THUMBS: string | ((html: HTMLElement) => Array<HTMLElement>);
147
- THUMB_DATA: {
148
- title: string;
149
- uploader?: string;
150
- duration?: string;
151
- } | ((thumb: HTMLElement) => {
152
- title: string;
153
- duration: number;
154
- });
155
- THUMB_IMG_DATA: {
156
- img?: string;
157
- imgSrc?: string;
158
- lazyloading?: string;
159
- } | ((thumb: HTMLElement) => {
160
- img?: HTMLElement;
161
- imgSrc?: string;
162
- });
163
- paginationUrlGenerator: ((offset: number) => string) | {
164
- searchPage?: string;
165
- pathnameLast?: boolean;
166
- };
167
- paginationElement: string | ((html?: HTMLElement) => HTMLElement);
141
+ declare interface IRules_2 {
142
+ paginationStrategy: PaginationStrategy;
143
+ delay: number;
168
144
  paginationOffset: number;
169
145
  paginationLast: number;
170
- CONTAINER: string | ((html?: HTMLElement) => HTMLElement);
171
- router?: (rules: RulesHelper, store: JabroniStore, handleHtmlCallback: (document: HTMLElement) => void, scroller: InfiniteScroller) => void;
172
- URL_DATA?: () => {
173
- paginationOffset: number;
174
- paginationUrlGenerator: (offset: number) => string;
175
- };
146
+ paginationElement: HTMLElement;
147
+ paginationUrlGenerator: (n: number) => string;
176
148
  }
177
149
 
178
150
  export declare function isMob(): boolean;
@@ -209,6 +181,17 @@ export declare class Observer {
209
181
 
210
182
  declare type OffsetGenerator = Generator<GeneratorResult> | AsyncGenerator<GeneratorResult>;
211
183
 
184
+ declare class PaginationStrategy {
185
+ doc: Document;
186
+ paginationSelector: string;
187
+ fixPaginationLast: (n: number) => number;
188
+ constructor(doc: Document, paginationSelector: string, fixPaginationLast: (n: number) => number);
189
+ getPaginationElement(): HTMLElement;
190
+ getPaginationLast(): number;
191
+ getPaginationOffset(): number;
192
+ getPaginationUrlGenerator(url_?: URL | Location | string): (n: number) => string;
193
+ }
194
+
212
195
  export declare function parseCSSUrl(s: string): string;
213
196
 
214
197
  export declare function parseDataParams(str: string): Record<string, string>;
@@ -221,37 +204,6 @@ export declare function range(size: number, startAt?: number, step?: number): nu
221
204
 
222
205
  export declare function replaceElementTag(e: HTMLElement | Element, tagName: string): HTMLElement;
223
206
 
224
- export declare class RulesHelper {
225
- private options;
226
- delay: number;
227
- IS_VIDEO_PAGE: boolean;
228
- IS_SEARCH_PAGE: boolean;
229
- paginationElement: HTMLElement;
230
- paginationOffset: number;
231
- paginationLast: number;
232
- URL_DATA: undefined | (() => {
233
- paginationOffset: number;
234
- paginationUrlGenerator: (offset: number) => string;
235
- });
236
- constructor(options: IRulesHelper);
237
- router(store: JabroniStore, handleHtmlCallback: (document: HTMLElement) => void): void;
238
- paginationUrlGenerator: (offset: number) => string;
239
- _IS_VIDEO_PAGE: () => boolean;
240
- _IS_SEARCH_PAGE: () => boolean;
241
- _paginationElement: (html?: Document) => HTMLElement;
242
- CONTAINER: (html?: Document) => HTMLElement;
243
- THUMB_URL: (thumb: HTMLElement) => string;
244
- GET_THUMBS: (html: HTMLElement) => HTMLElement[];
245
- THUMB_DATA: (thumb: HTMLElement) => {
246
- title: string;
247
- duration: number;
248
- };
249
- THUMB_IMG_DATA: (thumb: HTMLElement) => {
250
- img?: HTMLElement;
251
- imgSrc?: string;
252
- } | undefined;
253
- }
254
-
255
207
  export declare function sanitizeStr(s: string): string;
256
208
 
257
209
  export declare function stringToWords(s: string): Array<string>;
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.4.2",
4
+ "version": "1.4.4",
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)",
@@ -23,13 +23,10 @@ type FilterInput = Record<string, string | number | boolean | HTMLElement>;
23
23
  type FilterFunction = (v: FilterInput) => FilterResult;
24
24
 
25
25
  class DataFilter {
26
- private state: DataFilterState;
27
- private rules: IRules;
28
26
  public filters: { [key: string]: () => FilterFunction };
29
27
 
30
- constructor(rules: IRules, state: DataFilterState) {
28
+ constructor(private rules: IRules, private state: DataFilterState) {
31
29
  this.state = state;
32
- this.rules = rules;
33
30
 
34
31
  const methods = Object.getOwnPropertyNames(this);
35
32
  this.filters = methods.reduce((acc: { [key: string]: () => FilterFunction }, k) => {
@@ -44,7 +41,7 @@ class DataFilter {
44
41
 
45
42
  filterPublic = (): FilterFunction => {
46
43
  return (v: FilterInput) => {
47
- const isPublic = !this.rules.IS_PRIVATE(v.element as HTMLElement);
44
+ const isPublic = !this.rules.isPrivate(v.element as HTMLElement);
48
45
  return {
49
46
  tag: 'filter-public',
50
47
  condition: this.state.filterPublic && isPublic,
@@ -54,7 +51,7 @@ class DataFilter {
54
51
 
55
52
  filterPrivate = (): FilterFunction => {
56
53
  return (v: FilterInput) => {
57
- const isPrivate = this.rules.IS_PRIVATE(v.element as HTMLElement);
54
+ const isPrivate = this.rules.isPrivate(v.element as HTMLElement);
58
55
  return {
59
56
  tag: 'filter-private',
60
57
  condition: this.state.filterPrivate && isPrivate,
@@ -64,7 +61,7 @@ class DataFilter {
64
61
 
65
62
  filterHD = (): FilterFunction => {
66
63
  return (v: FilterInput) => {
67
- const isHD = this.rules.IS_HD(v.element as HTMLElement);
64
+ const isHD = this.rules.isHD(v.element as HTMLElement);
68
65
  return {
69
66
  tag: 'filter-hd',
70
67
  condition: this.state.filterHD && isHD,
@@ -108,13 +105,13 @@ class DataFilter {
108
105
  }
109
106
 
110
107
  interface IRules {
111
- GET_THUMBS: (html: HTMLElement) => HTMLElement[];
112
- THUMB_URL: (thumbElement: HTMLElement) => string;
113
- THUMB_DATA: (thumbElement: HTMLElement) => { title: string; duration: number };
114
- THUMB_IMG_DATA: (thumbElement: HTMLElement) => { img: HTMLElement; imgSrc: string };
115
- CONTAINER: HTMLElement;
116
- IS_PRIVATE: (element: HTMLElement) => boolean;
117
- IS_HD: (element: HTMLElement) => boolean;
108
+ getThumbs: (html: HTMLElement) => HTMLElement[];
109
+ getThumbUrl: (thumbElement: HTMLElement) => string;
110
+ getThumbData: (thumbElement: HTMLElement) => { title: string; duration: number };
111
+ getThumbImgData: (thumbElement: HTMLElement) => { img: HTMLElement; imgSrc: string };
112
+ container: HTMLElement;
113
+ isPrivate: (element: HTMLElement) => boolean;
114
+ isHD: (element: HTMLElement) => boolean;
118
115
  }
119
116
 
120
117
  export class DataManager {
@@ -191,25 +188,25 @@ export class DataManager {
191
188
  removeDuplicates = false,
192
189
  shouldLazify = true,
193
190
  ): void => {
194
- const thumbs = this.rules.GET_THUMBS(html);
191
+ const thumbs = this.rules.getThumbs(html);
195
192
  const data_offset = this.data.size;
196
193
 
197
194
  for (const thumbElement of thumbs) {
198
- const url = this.rules.THUMB_URL(thumbElement);
195
+ const url = this.rules.getThumbUrl(thumbElement);
199
196
  if (!url || this.data.has(url)) {
200
197
  if (removeDuplicates) thumbElement.remove();
201
198
  continue;
202
199
  }
203
200
 
204
- const data = this.rules.THUMB_DATA(thumbElement);
201
+ const data = this.rules.getThumbData(thumbElement);
205
202
  this.data.set(url, { element: thumbElement, ...data });
206
203
 
207
204
  if (shouldLazify) {
208
- const { img, imgSrc } = this.rules.THUMB_IMG_DATA(thumbElement);
205
+ const { img, imgSrc } = this.rules.getThumbImgData(thumbElement);
209
206
  this.lazyImgLoader.lazify(thumbElement, img as HTMLImageElement, imgSrc);
210
207
  }
211
208
 
212
- const parent = container || this.rules.CONTAINER;
209
+ const parent = container || this.rules.container;
213
210
  if (!parent.contains(thumbElement)) parent.appendChild(thumbElement);
214
211
  }
215
212
 
package/src/index.ts CHANGED
@@ -21,6 +21,4 @@ export { computeAsyncOneAtTime, AsyncPool, wait } from './utils/async';
21
21
  export { chunks, range } from './utils/arrays';
22
22
  export { DataManager } from './data-manager';
23
23
  export { InfiniteScroller } from './utils/infinite-scroll';
24
- export { RulesHelper } from './utils/userscript-utils/rules';
25
- export type { IRulesHelper } from './utils/userscript-utils/rules';
26
24
  export { createInfiniteScroller } from './utils/jabroni-outfit-wrap';
@@ -1,5 +1,14 @@
1
1
  import { InfiniteScroller } from '../infinite-scroll';
2
- import type { RulesHelper } from '../userscript-utils/rules';
2
+ import { PaginationStrategy } from '../userscript-utils/pagination-strategies';
3
+
4
+ interface IRules {
5
+ paginationStrategy: PaginationStrategy,
6
+ delay: number,
7
+ paginationOffset: number,
8
+ paginationLast: number,
9
+ paginationElement: HTMLElement,
10
+ paginationUrlGenerator: (n: number) => string;
11
+ }
3
12
 
4
13
  export interface JabroniStore {
5
14
  state: Record<string, boolean | string | number>;
@@ -10,9 +19,15 @@ export interface JabroniStore {
10
19
  export function createInfiniteScroller(
11
20
  store: JabroniStore,
12
21
  handleHtmlCallback: (document: HTMLElement) => void,
13
- rules: RulesHelper,
22
+ rules: IRules,
14
23
  ) {
15
24
  const enabled = store.state.infiniteScrollEnabled as boolean;
25
+
26
+ rules.paginationOffset = rules.paginationStrategy.getPaginationOffset();
27
+ rules.paginationLast = rules.paginationStrategy.getPaginationLast();
28
+ rules.paginationUrlGenerator = rules.paginationStrategy.getPaginationUrlGenerator();
29
+ rules.paginationElement = rules.paginationStrategy.getPaginationElement();
30
+
16
31
  const iscroller = new InfiniteScroller({
17
32
  enabled,
18
33
  handleHtmlCallback,
@@ -23,8 +23,9 @@ export function parseIntegerOr(n: string | number, or: number): number {
23
23
 
24
24
  // "data:02;body+head:async;void:;zero:;"
25
25
  export function parseDataParams(str: string): Record<string, string> {
26
- return str.split(';').reduce((acc, s) => {
27
- const parsed = s.match(/([\+\w]+):(\w+)?/);
26
+ const paramsStr = decodeURI(str.trim()).split(';');
27
+ return paramsStr.reduce((acc, s) => {
28
+ const parsed = s.match(/([\+\w]+):([\w\-\ ]+)?/);
28
29
  if (parsed) {
29
30
  const [, key, value] = parsed;
30
31
  if (value) {
@@ -0,0 +1,59 @@
1
+ import { parseDataParams } from "../parsers";
2
+
3
+ export class PaginationStrategy {
4
+ constructor(
5
+ public doc = document,
6
+ public paginationSelector = '.pagination:not([id *= member])',
7
+ public fixPaginationLast: (n: number) => number) {}
8
+
9
+ getPaginationElement() {
10
+ return this.doc.querySelector(this.paginationSelector) as HTMLElement;
11
+ }
12
+
13
+ getPaginationLast() {
14
+ const links = this.getPaginationElement()?.querySelectorAll('[data-parameters *= from]');
15
+ const pages = Array.from(links || [], (l) => {
16
+ const p = l.getAttribute('data-parameters');
17
+ const v = p?.match(/from\w*:(\d+)/)?.[1] || '1';
18
+ return parseInt(v);
19
+ });
20
+ const lastPage = Math.max(...pages, 1);
21
+ if (this.fixPaginationLast) return this.fixPaginationLast(lastPage);
22
+ return lastPage;
23
+ }
24
+
25
+ getPaginationOffset() {
26
+ const link = this.getPaginationElement()
27
+ ?.querySelector('.prev[data-parameters *= from], .prev [data-parameters *= from]');
28
+ if (!link) return 1;
29
+ const p = link.getAttribute('data-parameters');
30
+ const v = p?.match(/from\w*:(\d+)/)?.[1] || '1';
31
+ return parseInt(v);
32
+ }
33
+
34
+ getPaginationUrlGenerator(url_: URL | Location | string = location) {
35
+ const url = new URL(typeof url_ === 'string' ? url_ : url_.href);
36
+
37
+ const parametersElement = this.getPaginationElement()
38
+ ?.querySelector('a[data-block-id][data-parameters]');
39
+ const block_id = parametersElement?.getAttribute('data-block-id') || '';
40
+ const parameters = parseDataParams(parametersElement?.getAttribute('data-parameters') || '');
41
+
42
+ const attrs: Record<string, string> = {
43
+ mode: 'async',
44
+ function: 'get_block',
45
+ block_id,
46
+ ...parameters
47
+ };
48
+
49
+ Object.keys(attrs).forEach((k) => url.searchParams.set(k, attrs[k]));
50
+
51
+ const paginationUrlGenerator = (n: number) => {
52
+ Object.keys(attrs).forEach((k) => k.includes('from') && url.searchParams.set(k, n.toString()));
53
+ url.searchParams.set('_', Date.now().toString());
54
+ return url.href;
55
+ };
56
+
57
+ return paginationUrlGenerator;
58
+ }
59
+ }